"ant-design-vue": "^1.78"
树形控件渲染数据注意
对于异步请求的数据不能刷新页面,渲染数结构。
解决办法
-
在父组件中请求数据,传入子组件
-
使用
v-if判断请求数据是否完成,然后再进行渲染
搜索
对于antdv@1.7.8版本官网示例有些麻烦,可以考虑用chatGPT实现
原理是:根据输入内容,使用递归方法重新生成树data,形成新的树(并非唯一)
展开指定节点和默认展开
expandedKeys 会覆盖 defaultExpandedKeys
通过给expandedKeys赋值方式实现defaultExpandedKeys
组件封装
<template>
<a-spin :spinning="confirmLoading">
<div class="modal-tree">
<a-input-search placeholder="请输入树节点" v-model="searchValue" />
<a-tree
v-model="checkedKeys"
v-if="orgTree.length > 0"
:selectedKeys.sync="selectedKeys"
:show-line="true"
:show-icon="true"
:tree-data="filteredData"
:expanded-keys="expandedKeys"
:autp-expanded-parent="autoExpandedParent"
:checkable="checkable"
:checkStrictly="checkStrictly"
@select="onSelect"
@expand="onExpand"
@check="onCheck"
>
<img src="@/assets/gov-icon.png" slot="folder" />
<!-- title slot仅用于实现字体高亮 -->
<!-- 通过substr将title分成三部分。将含有搜索条件的字符串高亮显示 -->
<template slot="title" slot-scope="{ title }">
<span v-if="title.indexOf(searchValue) > -1">
{{ title.substr(0, title.indexOf(searchValue)) }}
<span
style="color: #f50"
>{{ searchValue }}</span>
{{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
</span>
<span v-else>{{ title }}</span>
</template>
</a-tree>
</div>
</a-spin>
</template>
<script>
import { getAction } from "@/api/manage";
export default {
props: {
treeType: {
type: String,
default: "depart",
required: true
},
checkable: {
type: Boolean,
default: false
},
hasChecked: {
type: Array,
default: () => []
}
},
data() {
return {
url: { // 请求路径
system: ""
},
orgTree: [], // 树结构完整数据
expandedKeys: [], // 展开指定节点
checkedKeys: [], // 复选框选中的树节点
autoExpandedParent: false,
searchValue: "", // 搜索条件
selectedKeys: [], // 点击某个树节点
nodeKeys: [], // 默认展开节点
confirmLoading: false,
checkStrictly: true // 父子不关联
};
},
computed: {
// 树实际渲染的数据
filteredData() {
if (!this.searchValue) {
return this.orgTree;
}
const filteredNodes = [];
this.orgTree.forEach(node => {
this.searchAndFilter(node, this.searchValue, filteredNodes);
});
return filteredNodes;
}
},
created() {
// 获取树数据
this.getTreeByType();
},
methods: {
// chatGPT生成的树的过滤方法
searchAndFilter(node, searchText, filteredNodes) {
// console.log(node)
if (node.title.includes(searchText)) {
filteredNodes.push(node);
// node.setExpanded(true);
}
if (node.children) {
node.children.forEach(childNode => {
this.searchAndFilter(childNode, searchText, filteredNodes);
});
}
},
getTreeByType() {
const body = {};
this.confirmLoading = true;
getAction(this.url[this.type], body)
.then(res => {
if (res.success) {
let list = Object.assign([], res.result); // 防止数据污染
this.eachIt(list);
this.orgTree = list;
console.log(this.orgTree, this.treeType);
// expandedKeys 会覆盖 defaultExpandedKeys
// 通过给expandedKeys赋值方式实现defaultExpandedKeys
this.expandedKeys = Object.assign([], this.nodeKeys);
this.checkedKeys = Object.assign([], this.hasChecked); // 已选中
} else {
this.$message.warning(res.message);
}
})
.finally(() => {
this.confirmLoading = false;
});
},
// 生成树结构
eachIt(children) {
children.forEach(item => {
item["title"] = item.name;
item["key"] = item.id;
item["slots"] = { icon: "folder" };
if (item.level == "1") {
// 默认展开一级树节点
this.nodeKeys.push(item.id);
}
if (item.children) {
this.eachIt(item.children);
}
});
},
/**
*
* @param {*} selectedKeys 节点的某种属性
* @param {*} info 完整数据
*/
onSelect(selectedKeys, info) {
this.$emit("select", selectedKeys, info);
},
// 实现展开指定节点
onExpand(expandedKeys) {
this.expandedKeys = expandedKeys;
this.autoExpandedParent = false;
},
onCheck(checkedKeys, info) {
if (this.checkStrictly) {
// 关联和不关联 checkedKeys 可能不同
this.checkedKeys = checkedKeys.checked;
} else {
this.checkedKeys = checkedKeys;
}
this.$emit("check", checkedKeys, info, this.checkedKeys);
}
}
};
</script>
<style scoped lang="less">
.modal-tree {
max-height: 679px;
overflow-y: scroll;
.search-box {
display: flex;
}
}
</style>