vue封装element-ui的el-checkbox实现嵌套多选组件
vue封装element-ui的el-checkbox实现嵌套多选组件要实现的效果如何使用<multi-check-list :dataList="dataList" :isCheckAll='true' @change="handlerDataCheck"></multi-check-list>import MultiCheckList from './multiChec
·
vue封装element-ui的el-checkbox实现嵌套多选组件,支持数据回显
个人博客
要实现的效果(2021-07-06更新支持反选)
数据回显需要绑定default-checked-keys(2022-03-24更新)
如何使用
<multi-check-list :dataList="dataList" :default-checked-keys="['a001','a003']" :invert="false" :isCheckAll='true' @change="handlerDataCheck"></multi-check-list>
import MultiCheckList from './multiCheckList.vue';
data() {
return {
dataList:[{
code:1001,
label:'电商',
value:'a001',
children:[{
code:1002,
label:'淘宝',
value:'a002'
}, {
code:1003,
label:'京东',
value:'a003'
}, {
code:1004,
label:'亚马逊',
value:'a002'
}]
}, {
code:1005,
label:'生活服务',
value:'a005',
children:[{
code:1006,
label:'美团',
value:'a006'
}, {
code:1007,
label:'大众点评',
value:'a007'
}, {
code:1008,
label:'滴滴',
value:'a008'
}, {
code:1009,
label:'饿了么',
value:'a009'
}]
}],
}
},
methods: {
handlerDataCheck(parent, child) {
console.log(parent, child)
},
}
具体实现
HTML
<template>
<div class="multi-check" :style="{width:width}">
<div class="multi-check-item" v-if="isCheckAll">
<el-checkbox label="全选" :indeterminate="isIndeterminate" v-model="checkAll" @change="handlerChange(0, null, $event)">全选 {{totalLabel}}</el-checkbox>
<el-checkbox label="反选" v-model="checkInvert" @change="handlerChange(-1, null, $event)">反选</el-checkbox>
</div>
<div class="multi-check-item" v-for="(item) in newDataList" :key="item.code">
<el-checkbox v-model="item.isChecked" :indeterminate="item.isIndeterminate" :label="item.code" :value="item.value" @change="handlerChange(1, item, $event)">{{item.label}}</el-checkbox>
<div class="multi-check-item" style="display:inline-block">
<el-checkbox v-model="child.isChecked" @change="handlerChange(2, item, $event)" v-for="child in (item.children || [])" :key="child.code" :label="child.value">{{child.label}}</el-checkbox>
</div>
</div>
</div>
</template>
JavaScript
<script>
export default {
name:'multiCheckList',
props: {
isCheckAll: { //是否显示全选
type: Boolean,
default: false
},
invert:{ //是否显示反选(2021-07-06更新)
type:Boolean,
default:false
},
dataList:{ //数据集合
type: Array,
required: true
},
width:{
type: String,
default:'100%'
},
defaultCheckedKeys:{ //默认选中项
type:Array,
default:() => ([])
}
},
data() {
return {
checkAll:false,
checkInvert:false, //反选(2021-07-06更新)
isIndeterminate:false,
totalLabel:'',
newDataList:[] //为了不污染prop dataList
}
},
watch: {
newDataList: {
handler() {
const isChangeSum = this.newDataList.reduce((prev, cur) => {
return prev + (+(cur.isChange || 0));
}, 0);
const isCheckSum = this.newDataList.reduce((prev, cur) => {
return prev + (+(cur.isChecked || 0));
}, 0);
this.checkAll = (isCheckSum && isCheckSum === this.newDataList.length);
this.isIndeterminate = !!isChangeSum;
if(isCheckSum && isCheckSum === this.newDataList.length) {
this.isIndeterminate = false;
}
this.totalLabel = isChangeSum === 0 ? "" : `已选择(${isChangeSum})个分类`;
},
immediate: true,
deep:true
},
dataList: {
handler:function(val) {
//这里只做简单的拷贝,深拷贝需要自己实现,这里只是为了演示
this.newDataList = JSON.parse(JSON.stringify(val))
this.initCheckedKeys()
},
immediate:true,
deep:true
}
},
computed: {
getDataList() {
let parentList = []
let childList = []
this.newDataList.forEach(item => {
if(item.isChecked) parentList.push(item.value)
;(item.children || []).forEach(child => {
if(child.isChecked) {
childList.push(child.value);
}
})
})
return [parentList, childList]
}
},
methods: {
initCheckedKeys() { //初始化默认选中项
;(this.newDataList || []).forEach(item => {
if(!item.children || !Array.isArray(item.children)) item.children = []
item.children.forEach(child => {
if(this.defaultCheckedKeys.includes(child.value)) {
this.$set(child, 'isChecked', true);
}
});
if(item.children.length) {
const every = item.children.every(it => it.isChecked) //子集全部选中
const some = item.children.some(it => it.isChecked) //子集没有全部选中
this.$set(item, 'isChecked', every);
this.$set(item, 'isIndeterminate', some && !every);
this.$set(item, 'isChange', some)
}
})
},
handlerCheckAll(isChecked) {
this.newDataList.forEach(item => {
this.$set(item, 'isChecked', isChecked);
this.$set(item, 'isChange', isChecked);
if(isChecked) this.$set(item, 'isIndeterminate', false);
item.children.forEach(child => {
this.$set(child, 'isChecked', isChecked);
})
});
},
handlerInvertCheck() { //反选(2021-07-06更新)
this.newDataList.forEach(item => {
this.$set(item, 'isChange', !item.isChecked);
this.$set(item, 'isChecked', !item.isChecked);
item.children.forEach(child => {
this.$set(child, 'isChecked', !child.isChecked);
if(child.isChecked) this.$set(item, 'isChange', true);
})
});
},
handlerChange($type, $row, $event) {
let isChecked = !$event.target ? $event: $event.target.checked;
if($type === 0) { //全选
this.handlerCheckAll(isChecked)
this.$emit('change', this.getDataList[0],this.getDataList[1])
return
}
if($type === 1) {
$row.children.forEach((item) => {
this.$set(item, 'isChecked', isChecked);
})
}
if($type === -1) { //反选(2021-07-06更新)
this.handlerInvertCheck()
this.$emit('change', this.getDataList[0],this.getDataList[1])
return
}
const checkCount = $row.children.reduce((prev, cur)=> {
let check = 0;
if(cur.isChecked === undefined) {
check = 0;
}else {
check = +cur.isChecked
}
return prev + (+check);
},0); //统计选择的次数
this.$set($row, 'isChange', checkCount === 0 ? false: true);
this.$set($row, 'isChecked', (checkCount && checkCount === $row.children.length) ? true: false);
this.$set($row, 'isIndeterminate', (checkCount && checkCount < $row.children.length) ? true:false);
this.$emit('change', this.getDataList[0],this.getDataList[1])
}
}
}
</script>
css
<style lang="scss" scoped>
.multi-check {
position: relative;
text-align:left;
.multi-check-item {
width: 100%;
background-color: #F9FAFB;
padding: 10px 0;
padding-left: 25px;
margin-bottom: 10px;
border-radius: 6px;
}
}
</style>
更多推荐
已为社区贡献2条内容
所有评论(0)