基于Vue和Element-UI自定义分组以及分组全选Select 选择器
上一篇博文我们已经实现了基于Vue和Element-UI中Select 选择器的分组全选以及样式修改问题, 但是在分组方面我们是用了element-ui 自带的使用el-option-group对备选项进行分组,它的label属性为分组名
的功能,但是出来的效果样式很难自定义,就算是魔改element的样式也有一些改不了的。
比如我们的需求就是需要把分组全选框移动到分组名旁边,然后还需要对选项进行列对齐
那我们最终需要实现的效果就是
并优化了一些文字过长的样式问题。
话不多说,具体的问题我们在上一篇博文也都讲到了,感兴趣的可以移至上一篇博文查看。下面我们直接来看代码吧
<template>
<div>
<el-select v-model="value" placeholder="请选择" @change="changeSelect" style="width: 250px" clearable multiple collapse-tags size="small"
popper-class="productGroupSelector" class="productGroup-select">
<div v-for="group in options" :key="group.label" class="productGroupSelector-group">
<div style="display: flex;align-items: center; padding-top: 8px; padding-left: 5px">
<el-checkbox v-model="group.checked" @change='selectAll($event,group.id)' :indeterminate="group.isIndeterminate"></el-checkbox>
<div class="productGroupSelector-group-title">{{group.label}}</div>
</div>
<div style="display: flex; align-items: start;">
<div style="width: 400px">
<el-option class="productGroupSelector-option"
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="group.label + '-' + item.value">
<div class="productGroupSelector-option-content">{{ item.label }}</div>
</el-option>
</div>
</div>
</div>
</el-select>
</div>
</template>
<script>
export default {
name: 'SelectorComponent2',
data () {
return {
options: [{
id: 1,
label: '热门城市',
checked: false,
isIndeterminate: false,
options: [{
value: 'Shanghai',
label: '上海'
}, {
value: 'Beijing',
label: '北京'
}]
}, {
id: 2,
label: '城市名',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu',
label: '成都'
}, {
value: 'Shenzhen',
label: '深圳'
}, {
value: 'Guangzhou',
label: '广州'
}, {
value: 'Dalian',
label: '大连'
},
{
value: 'Huizhou',
label: '惠州'
}]
},
{
id: 3,
label: '城市名2',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu2',
label: '成都22222'
}, {
value: 'Shenzhen2',
label: '深圳22222'
}, {
value: 'Guangzhou2',
label: '广州2222'
}, {
value: 'Dalian2',
label: '大连222222222222'
},
{
value: 'Huizhou2',
label: '惠州2'
}]
},
{
id: 4,
label: '城市名3',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu3',
label: '成都333'
}, {
value: 'Shenzhen3',
label: '深圳3'
}, {
value: 'Guangzhou3',
label: '广州33'
}, {
value: 'Dalian3',
label: '大连33333111111111111111333'
},
{
value: 'Huizhou3',
label: '惠州3'
}]
}],
value: ''
}
},
methods: {
onChange (value) {
console.log(value)
console.log(this.value)
},
selectAll (val, id) {
const selectOption = this.options.find(f => f.id === id)
const arr = selectOption.options.map(m => selectOption.label + '-' + m.value)
if (val) {
arr.forEach(item => {
if (!this.value.includes(item)) {
this.value.push(item)
}
})
} else {
this.value.forEach((item, index) => {
if (arr.includes(item)) {
this.value.splice(index, 1, '')
}
})
}
this.value = this.value.filter(f => f !== '')
if (selectOption.checked) {
selectOption.isIndeterminate = false
}
},
changeSelect (val) {
this.options.forEach(item => {
const arr = item.options.map(m => item.label + '-' + m.value)
item.isIndeterminate = arr.some((v) => {
return val.some(s => s === v)
})
item.checked = arr.every((v) => {
return val.some(s => s === v)
})
if (item.checked) {
item.isIndeterminate = false
}
})
}
}
}
</script>
<style lang="less" scoped>
.productGroupSelector-group {
padding-top: 10px;
display: flex;
align-items: center;
flex-wrap: wrap;
width: 400px;
padding-bottom: 10px;
&-title {
padding-left: 5px;
font-weight:bold
}
&:after {
display: none;
}
}
.productGroupSelector-option {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
width: 200px;
&-content {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
.productGroup-select /deep/ .el-select__tags-text:first-child{
max-width: 120px;
}
</style>
<style lang="less">
.productGroupSelector {
.el-scrollbar__view.el-select-dropdown__list {
width: 800px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
padding-top: 0;
overflow-x: hidden;
}
}
.productGroupSelector {
.el-select-dropdown__wrap.el-scrollbar__wrap {
max-height: 350px
}
}
</style>
再进一步优化,自适应浏览器,当浏览器窗口变化的时候,下拉框的内容能够自适应
<template>
<div>
<el-select v-model="value" placeholder="请选择" @change="changeSelect" style="width: 250px" clearable multiple collapse-tags size="small"
popper-class="productGroupSelector" class="productGroup-select">
<div v-for="group in options" :key="group.label" class="productGroupSelector-group">
<div style="display: flex;align-items: center; padding-top: 8px; padding-left: 5px">
<el-checkbox v-model="group.checked" @change='selectAll($event,group.id)' :indeterminate="group.isIndeterminate"></el-checkbox>
<div class="productGroupSelector-group-title">{{group.label}}</div>
</div>
<div style="display: flex; align-items: start;">
<div class="productGroupSelector-option-root">
<el-option class="productGroupSelector-option"
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="group.label + '-' + item.value">
<div class="productGroupSelector-option-content">{{ item.label }}</div>
</el-option>
</div>
</div>
</div>
</el-select>
</div>
</template>
<script>
export default {
name: 'SelectorComponent3',
data () {
return {
options: [{
id: 1,
label: '热门城市',
checked: false,
isIndeterminate: false,
options: [{
value: 'Shanghai',
label: '上海'
}, {
value: 'Beijing',
label: '北京'
}]
}, {
id: 2,
label: '城市名',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu',
label: '成都'
}, {
value: 'Shenzhen',
label: '深圳'
}, {
value: 'Guangzhou',
label: '广州'
}, {
value: 'Dalian',
label: '大连'
},
{
value: 'Huizhou',
label: '惠州'
}]
},
{
id: 3,
label: '城市名2',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu2',
label: '成都22222'
}, {
value: 'Shenzhen2',
label: '深圳22222'
}, {
value: 'Guangzhou2',
label: '广州2222'
}, {
value: 'Dalian2',
label: '大连222222222222'
},
{
value: 'Huizhou2',
label: '惠州2'
}]
},
{
id: 4,
label: '城市名3',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu3',
label: '成都333'
}, {
value: 'Shenzhen3',
label: '深圳3'
}, {
value: 'Guangzhou3',
label: '广州33'
}, {
value: 'Dalian3',
label: '大连33333111111111111111333'
},
{
value: 'Huizhou3',
label: '惠州3'
}]
}],
value: ''
}
},
methods: {
selectAll (val, id) {
const selectOption = this.options.find(f => f.id === id)
const arr = selectOption.options.map(m => selectOption.label + '-' + m.value)
if (val) {
arr.forEach(item => {
if (!this.value.includes(item)) {
this.value.push(item)
}
})
} else {
this.value.forEach((item, index) => {
if (arr.includes(item)) {
this.value.splice(index, 1, '')
}
})
}
this.value = this.value.filter(f => f !== '')
if (selectOption.checked) {
selectOption.isIndeterminate = false
}
},
changeSelect (val) {
this.options.forEach(item => {
const arr = item.options.map(m => item.label + '-' + m.value)
item.isIndeterminate = arr.some((v) => {
return val.some(s => s === v)
})
item.checked = arr.every((v) => {
return val.some(s => s === v)
})
if (item.checked) {
item.isIndeterminate = false
}
})
}
}
}
</script>
<style lang="less" scoped>
@selectGroupWidth: 400px;
.productGroupSelector-group {
padding-top: 10px;
display: flex;
align-items: center;
flex-wrap: wrap;
width: @selectGroupWidth;
padding-bottom: 10px;
&-title {
padding-left: 5px;
font-weight:bold
}
&:after {
display: none;
}
}
.productGroupSelector-option-root {
width: @selectGroupWidth;
}
.productGroupSelector-option {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
width: (@selectGroupWidth / 2);
&-content {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
.productGroup-select /deep/ .el-select__tags-text:first-child{
max-width: 120px;
}
</style>
<style lang="less">
@selectWidth: 800px;
.productGroupSelector {
.el-scrollbar__view.el-select-dropdown__list {
width: @selectWidth;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
padding-top: 0;
@media screen and (max-width: @selectWidth) {
width: (@selectWidth/2);
}
}
}
.productGroupSelector {
.el-select-dropdown__wrap.el-scrollbar__wrap {
max-height: 350px
}
}
</style>
效果如下:
(更新于2022年4月1日)
更新了一下样式
<template>
<div>
<el-select v-model="value" placeholder="请选择" @change="changeSelect" style="width: 250px" clearable multiple collapse-tags size="small"
popper-class="productGroupSelector" class="productGroup-select">
<div v-for="group in options" :key="group.label" class="productGroupSelector-group">
<div style="display: flex;align-items: center; padding-top: 8px; padding-left: 5px">
<el-checkbox v-model="group.checked" @change='selectAll($event,group.id)' :indeterminate="group.isIndeterminate"></el-checkbox>
<div class="productGroupSelector-group-title">{{group.label}}</div>
</div>
<div style="display: flex; align-items: start;">
<div class="productGroupSelector-option-root">
<el-option class="productGroupSelector-option"
v-for="item in group.options"
:key="item.value"
:label="item.label"
:value="group.label + '-' + item.value">
<div class="productGroupSelector-option-content">{{ item.label }}</div>
</el-option>
</div>
</div>
</div>
</el-select>
</div>
</template>
<script>
export default {
name: 'SelectorComponent4',
data () {
return {
options: [{
id: 1,
label: '热门城市',
checked: false,
isIndeterminate: false,
options: [{
value: 'Shanghai',
label: '上海'
}, {
value: 'Beijing',
label: '北京'
}]
}, {
id: 2,
label: '城市名',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu',
label: '成都'
}, {
value: 'Shenzhen',
label: '深圳'
}, {
value: 'Guangzhou',
label: '广州'
}, {
value: 'Dalian',
label: '大连'
},
{
value: 'Huizhou',
label: '惠州'
}]
},
{
id: 3,
label: '城市名2',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu2',
label: '成都22222'
}, {
value: 'Shenzhen2',
label: '深圳22222'
}, {
value: 'Guangzhou2',
label: '广州2222'
}, {
value: 'Dalian2',
label: '大连222222222222'
},
{
value: 'Huizhou2',
label: '惠州2'
}]
},
{
id: 4,
label: '城市名3',
checked: false,
isIndeterminate: false,
options: [{
value: 'Chengdu3',
label: '成都333'
}, {
value: 'Shenzhen3',
label: '深圳3'
}, {
value: 'Guangzhou3',
label: '广州33'
}, {
value: 'Dalian3',
label: '大连33333111111111111111333'
},
{
value: 'Huizhou3',
label: '惠州3'
}]
}],
value: ''
}
},
methods: {
selectAll (val, id) {
const selectOption = this.options.find(f => f.id === id)
const arr = selectOption.options.map(m => selectOption.label + '-' + m.value)
if (val) {
arr.forEach(item => {
if (!this.value.includes(item)) {
this.value.push(item)
}
})
} else {
this.value.forEach((item, index) => {
if (arr.includes(item)) {
this.value.splice(index, 1, '')
}
})
}
this.value = this.value.filter(f => f !== '')
if (selectOption.checked) {
selectOption.isIndeterminate = false
}
},
changeSelect (val) {
this.options.forEach(item => {
const arr = item.options.map(m => item.label + '-' + m.value)
item.isIndeterminate = arr.some((v) => {
return val.some(s => s === v)
})
item.checked = arr.every((v) => {
return val.some(s => s === v)
})
if (item.checked) {
item.isIndeterminate = false
}
})
}
}
}
</script>
<style lang="less" scoped>
@selectGroupWidth: 450px;
.productGroupSelector-group {
padding-top: 10px;
display: flex;
align-items: center;
flex-wrap: wrap;
width: @selectGroupWidth;
padding-bottom: 10px;
&-title {
padding-left: 5px;
font-weight:bold
}
&:after {
display: none;
}
}
.productGroupSelector-option-root {
width: @selectGroupWidth;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item{
padding-right: 0;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected:after{
left: 5px;
}
.productGroup-select /deep/ .el-select__tags-text:first-child{
max-width: 120px;
}
.productGroupSelector-option {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
width: (@selectGroupWidth / 3);
&-content {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
.productGroup-select /deep/ .el-select__tags-text:first-child{
max-width: 120px;
}
</style>
<style lang="less">
@selectWidth: 900px;
.productGroupSelector {
.el-scrollbar__view.el-select-dropdown__list {
width: @selectWidth;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
padding-top: 0;
@media screen and (max-width: @selectWidth) {
width: (@selectWidth/2);
}
}
}
.productGroupSelector {
.el-select-dropdown__wrap.el-scrollbar__wrap {
max-height: 350px
}
}
</style>
文章来源:https://www.toymoban.com/news/detail-405202.html
源代码
https://gitee.com/cckevincyh/vue-elementui文章来源地址https://www.toymoban.com/news/detail-405202.html
到了这里,关于基于Vue和Element-UI自定义分组以及分组全选Select 选择器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!