代码封装组件
<template>
<el-select ref="select" :value="value" :placeholder="placeholder" @visible-change="visibleChange" clearable
style="width: 100%" @clear="clear">
<el-option ref="option" class="option" :value="optionData.id" :label="optionData.name">
<el-tree ref="tree" class="tree" :node-key="nodeKey" :data="data" :props="props"
:default-expanded-keys="[value]" highlight-current :expand-on-click-node="false"
@node-click="handleNodeClick" :filter-node-method="onlyLeaf ? filterLeafNode : null"></el-tree>
</el-option>
</el-select>
</template>
<script>
export default {
name: "TreeSelect",
model: {
prop: "value",
event: "change",
},
props: {
// v-model绑定
value: {
type: [String, Number],
default: "",
},
// 树形的数据
data: {
type: Array,
default: function () {
return [];
},
},
// 每个树节点用来作为唯一标识的属性
nodeKey: {
type: [String, Number],
default: "id",
},
// tree的props配置
props: {
type: Object,
default: function () {
return {
label: "label",
children: "children",
};
},
},
placeholder: {
type: String,
default: "请选择",
},
// 是否显示全路径
showFullPath: {
type: Boolean,
default: false,
},
// 是否只能选择最后一级
onlyLeaf: {
type: Boolean,
default: false,
},
},
data() {
return {
optionData: {
id: "",
name: "",
},
};
},
watch: {
value: function (val) {
if (!this.isEmpty(this.data)) {
this.init(val);
}
},
data: function (val) {
if (!this.isEmpty(val)) {
this.init(this.value);
}
},
},
mounted() {
if (!this.isEmpty(this.data)) {
this.init(this.value);
}
},
methods: {
// 是否为空
isEmpty(val) {
for (let key in val) {
return false;
}
return true;
},
handleNodeClick(data,node) {
if (this.onlyLeaf && data[this.props.children] && data[this.props.children].length > 0){
node.expanded = !node.expanded
return;
}
let label = this.props.label || "name";
this.$emit("change", data[this.nodeKey]);
if (this.showFullPath) {
// If showFullPath is true, concatenate the full path
let fullPath = this.getFullPath(node, label);
this.optionData.name = fullPath;
} else {
this.optionData.name = data[label];
}
this.optionData.id = data[this.nodeKey];
// this.optionData.name = data[label];
this.$refs.select.visible = false;
},
init(val) {
if (val) {
this.$nextTick(() => {
let label = this.props.label || "name";
this.$refs.tree.setCurrentKey(val);
let node = this.$refs.tree.getNode(val);
this.optionData.id = val;
// this.optionData.name = node.label;
if (this.showFullPath) {
let fullPath = this.getFullPath(node, label);
this.optionData.name = fullPath;
} else {
this.optionData.name = node.label;
}
});
} else {
this.$refs.tree.setCurrentKey(null);
}
},
visibleChange(e) {
if (e) {
let selectDom = document.querySelector(".is-current");
setTimeout(() => {
this.$refs.select.scrollToOption({ $el: selectDom });
}, 0);
}
},
getFullPath(node, label) {
let path = node.data[label];
let parent = node.parent;
while (parent && parent.data &&parent.level>0) {
path = parent.data[label] + '/' + path;
parent = parent.parent;
}
return path;
},
// Method to filter non-leaf nodes if onlyLeaf is true
filterLeafNode(value, data) {
if (!value) return true;
return !data[this.props.children] || data[this.props.children].length === 0;
},
clear() {
this.$emit("change", "");
},
},
};
</script>
<style lang="scss" scoped>
.option {
height: auto;
line-height: 1;
padding: 0;
background-color: #fff;
}
.tree {
padding: 4px 20px;
font-weight: 400;
}
</style>
使用
<template>
<div class="app-container">
<el-row>
<tree-select
v-model="value"
:data="list"
style="width: 240px"
></tree-select>
</el-row>
</div>
</template>
<script>
import treeSelect from "@/components/selectTree";
export default {
components: {
treeSelect,
},
data() {
return {
list: [{
label: '系统',
id: 1,
children: [
{ label: '用户', id: 2 },
{ label: '用户组', id: 3 },
{ label: '角色', id: 4 },
{ label: '菜单', id: 5 },
{ label: '组织架构', id: 6 }
]
},
{
label: '商品',
id: 7,
children: [
{ label: '列表', id: 8 },
{ label: '添加', id: 9 },
{ label: '修改', id: 10 },
{ label: '删除', id: 11 },
{ label: '商品分类', id: 12 },
{ label: '分类修改', id: 13 }
]
}],
value: 1
};
},
};
</script>