封装antdv的仅适用于级联 TreeSelect 树型选择控件
1. 效果
-
支持多选
-
不支持多选
2. 组件
<template>
<a-tree-select
style="width: 100%"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
:value="currentValue"
:multiple="multiple"
:allow-clear="allowClear"
:placeholder="placeholder"
:tree-default-expand-all="treeDefaultExpandAll"
:treeNodeFilterProp="treeNodeFilterProp"
:replaceFields="replaceFields"
:tree-data="treeData"
:labelInValue="true"
@change="onChange"
/>
</template>
<script>
export default {
name: "TreeSelect",
props: {
// 选择框默认文字
placeholder: {
type: String,
required: false,
default: "",
},
// 替换 treeNode 中 title,value,key,children 字段为 treeData 中对应的字段
replaceFields: {
type: Object,
required: false,
default: () => {
return {
children: "children",
title: "title",
key: "key",
value: "value",
};
},
},
// 是否展开所有树节点
treeDefaultExpandAll: {
type: Boolean,
required: false,
default: false,
},
// 输入项过滤对应的 treeNode 属性
treeNodeFilterProp: {
type: String,
required: false,
default: "value",
},
// 是否显示清除按钮
allowClear: {
type: Boolean,
required: false,
default: true,
},
// 是否支持多选(当设置 treeCheckable 时自动变为 true)
multiple: {
type: Boolean,
required: false,
default: true,
},
// 数据
treeData: {
type: Array,
required: true,
},
},
data() {
return {
currentValue: undefined,
};
},
methods: {
// 选中树节点时调用此函数
onChange(val) {
let { title } = this.replaceFields;
this.currentValue = val;
// 支持多选
if (val.constructor == Array) {
val.forEach((item) => {
item.label = this.getTreePath(
this.treeData,
title,
(v) => v.value === item.value
);
});
} else {
// val.constructor == Object 的情况 // 不支持多选
val.label = this.getTreePath(this.treeData, title, (v) => v.value === val.value);
}
this.$emit("Change", val);
},
/**
* 获取树形数据的某个元素的所有父节点
* @param {tree} 属性tree-data的数据
* @param {title} 根据 title 去查询父级的显示内容
* @param {func} 自定义查询的参数名,匹配目标节点值
* @param {path} 存储目标元素的所有父节点的数组
* @return {*} 涵盖某个元素的所有父节点 ['level1','level2','level3']
*/
getTreePath(tree, title, func, path = []) {
if (!tree) return [];
for (const i of tree) {
path.push(i[title]); // push 树节点显示的内容
if (func(i)) return this.formatPath(path);
if (i.children) {
const findChildren = this.getTreePath(i.children, title, func, path);
if (findChildren.length) return findChildren;
}
path.pop();
}
return [];
},
/**
* 将父子级数组 ['level1','level2','level3'] 转换成级联 level1/level2/level3 格式
* @param {path} 节点label数组
* @return {*} label/label/label格式字符串
*/
formatPath(path) {
let str = "";
path.forEach((item) => {
item = item.trim();
str = str + item + "/";
});
return str.slice(0, str.length - 1);
},
},
};
</script>
3. 使用
<template>
<TreeSelect
:tree-data="treeData"
v-model="value"
placeholder="Please select"
:replaceFields="replaceFields"
:multiple='false' // 重点 - true表示支持多选 false表示支持单选
/>
</template>
<script>
import TreeSelect from "./TreeSelect.vue";
const treeData = [
{
label: "Node1",
value: "0-0",
key: "0-0",
children: [
{
label: "Child Node1",
value: "0-0-0",
key: "0-0-0",
children: [
{
label: "Child Node1-1",
value: "0-0-0-0",
key: "0-0-0-0",
},
],
},
],
},
{
label: "Node2",
value: "0-1",
key: "0-1",
children: [
{
label: "Child Node3",
value: "0-1-0",
key: "0-1-0",
disabled: true,
},
{
label: "Child Node4",
value: "0-1-1",
key: "0-1-1",
},
{
label: "Child Node5",
value: "0-1-2",
key: "0-1-2",
},
],
},
];
export default {
components: { TreeSelect },
data() {
return {
value: [],
treeData,
replaceFields: {
key: "key",
value: "value",
children: "children",
title: "label",
},
};
}
};
</script>