1、效果

2、组件代码
<template>
<div style="width: 370px">
<div>
<el-input placeholder="输入关键字进行过滤" v-model="filterText"
>></el-input
>
</div>
<el-tree
:data="treeData"
:props="defaultProps"
:width="treeWidth"
@node-click="handleNodeClick"
node-key="id"
:expand-on-click-node="false"
:filter-node-method="filterNode"
default-expand-all
ref="mapTree"
>
<span class="custom-tree-node" slot-scope="{ data }">
<span>{{ data.label }}</span>
<span>
<el-switch
v-model="data.isChecked"
active-color="#13ce66"
inactive-color="#608060"
:width="35"
:active-value="true"
:inactive-value="false"
@change="switchOpenOrClose(data)"
>
</el-switch>
</span>
</span>
</el-tree>
</div>
</template>
<script>
export default {
name: "SwitchTree",
props: {
treeData: {
type: Array,
},
treeWidth: {
type: Number,
default: 200,
},
},
data() {
return {
filterText: "",
defaultProps: {
children: "children",
label: "label",
},
};
},
methods: {
handleNodeClick() {},
switchOpenOrClose(data) {
this.$emit("openswitch", data);
this.setSwitchStatus(data.id, this.treeData, data.isChecked);
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
setSwitchStatus(id, data, status) {
let that = this;
data.forEach((x) => {
if (x.id == id) {
x.isChecked = status;
if (x.children) {
x.children.forEach((o) => {
that.setSwitchStatus(o.id, x.children, status);
});
}
} else {
if (x.children) {
that.setSwitchStatus(id, x.children, status);
}
}
});
this.setParentSwitcStatus(this.treeData[0]);
},
setParentSwitcStatus(data) {
let that = this;
let isChecked = true;
if (data.children) {
data.children.forEach((x) => {
if (!x.isChecked) {
isChecked = false;
}
if (x.children) {
that.setParentSwitcStatus(x);
}
});
}
data.isChecked = isChecked;
},
},
watch: {
filterText(val) {
this.$refs.mapTree.filter(val);
},
},
};
</script>
<style scoped>
.custom-tree-node /deep/ .el-switch__core {
width: 35px;
height: 15px;
}
.custom-tree-node /deep/ .el-switch__core::after {
height: 12px;
width: 12px;
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>
3、使用示例
<template>
<div>
<switch-tree
:treeData="data"
@openswitch="openOrCloseSwitch"
></switch-tree>
</div>
</template>
<script>
import SwitchTree from "./SwitchTree.vue";
export default {
name: "HelloWorld",
components: {
SwitchTree,
},
props: {
treeWith: {
type: Number,
default: 200,
},
},
data() {
return {
filterText: "",
data: [
{
id: 1,
label: "一级",
isChecked: false,
children: [
{
id: 2,
label: "二级 1-1",
isChecked: false,
children: [
{
id: 3,
label: "三级 1-1-1",
isChecked: false,
},
{
id: 4,
label: "三级 1-1-2",
},
],
},
],
},
{
id: 5,
label: "一级",
isChecked: true,
},
],
};
},
methods: {
openOrCloseSwitch(data) {
if (data.isChecked) {
console.log("open");
} else {
console.log("close");
}
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>