嵌套多选框
template
vue
<template>
<div class="multi-check" :style="{ width: width }">
<div class="multi-check-item" v-if="isCheckAll">
<el-checkbox
:indeterminate="isIndeterminate"
v-model="checkAll"
@change="handlerChange(0,null,$event)"
>全选{{ totalLabel }}</el-checkbox
>
</div>
<div class="multi-check-item" v-for="item in dataList" :key="item.code">
<el-checkbox
v-model="item.isChecked"
:indeterminate="item.indeterminate"
:label="item.code"
:value="item.value"
@change="handlerChange(1, item, $event)"
>
{{ item.label }}
</el-checkbox>
<div class="multi-check-item">
<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>
JS
vue
<script>
export default {
name: "multiCheckList",
//传入三个参数 是否全选 数据数组 宽度
props: {
isCheckAll: {
type: Boolean,
default: false,
},
dataList: {
type: Array,
required: true,//必须传入
},
width: {
type: String,
default: "100%",
},
},
data() {
return {
checkAll: false,//是否权限
isIndeterminate: false,//全选按钮样式
totalLabel: "", //总计标签
};
},
watch: {
dataList: {
handler() {
const isChangeSum = this.dataList.reduce((prev, cur) => {
return prev + (cur.isChange || 0);
}, 0); //计算改变的个数
const isCheckSum = this.dataList.reduce((prev, cur) => {
return prev + (cur.isChecked || 0);
}, 0); //统计选择的次数
this.checkAll = isCheckSum && isCheckSum === this.dataList.length;
this.isIndeterminate = !!isChangeSum; //!!转换为Boolean值
if (isCheckSum && isCheckSum === this.dataList.length) {
this.isIndeterminate = false;
}
this.totalLabel =
isChangeSum === 0 ? "" : `已选择(${isChangeSum})个分类`;
},
immediate: true,
deep: true,
},
},
computed: {
getDataList() {
//获取DataList内父级和子级被选中
let parentList = [];
let childList = [];
this.dataList.forEach((item) => {
if (item.isChecked) parentList.push(item.value);
(item.children || []).forEach((child) => {
if (child.isChecked) {
childList.push(child.value);
}
});
});
return [parentList, childList];
},
},
methods: {
//控制全选 通过遍历的方法 给每一级设置是否选中和是否改变
handlerCheckAll(isChecked) {
this.dataList.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);
});
});
},
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);
});
}
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>
使用
vue
<multi-check-list :dataList="dataList" :isCheckAll="true" @change="handlerDataCheck"/>
/*
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'
}]
}],
}
},
*/