1. 主要思路:
- 监听输入框内容,过滤
treeData,仅保留匹配项及其父级。 - 在
title渲染时,高亮匹配部分的文本。
2. 代码实现:
<template>
<div>
<a-input v-model="searchValue" placeholder="请输入关键字" @input="onSearch" style="margin-bottom: 10px;" />
<a-tree
:tree-data="expandedTreeData"
:expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent"
>
<template #title="{ title }">
<span v-html="getHighlightedText(title)"></span>
</template>
</a-tree>
</div>
</template>
<script>
export default {
data() {
return {
searchValue: "",
expandedKeys: [],
autoExpandParent: true,
treeData: [
{
title: "一级 1",
key: "0-1",
children: [
{ title: "二级 1-1", key: "0-1-1" },
{ title: "二级 1-2", key: "0-1-2" }
]
},
{
title: "一级 2",
key: "0-2",
children: [
{ title: "二级 2-1", key: "0-2-1" },
{ title: "二级 2-2", key: "0-2-2" }
]
}
],
expandedTreeData: []
};
},
created() {
this.expandedTreeData = this.treeData;
},
methods: {
onSearch() {
const searchValue = this.searchValue.trim();
if (!searchValue) {
this.expandedTreeData = this.treeData;
this.expandedKeys = [];
return;
}
const expandedKeys = [];
const filterTreeData = (data) => {
return data
.map((item) => {
const titleMatch = item.title.includes(searchValue);
if (titleMatch) expandedKeys.push(item.key);
if (item.children) {
const filteredChildren = filterTreeData(item.children);
if (filteredChildren.length || titleMatch) {
return { ...item, children: filteredChildren };
}
}
return titleMatch ? item : null;
})
.filter(Boolean);
};
this.expandedTreeData = filterTreeData(this.treeData);
this.expandedKeys = expandedKeys;
this.autoExpandParent = true;
},
getHighlightedText(text) {
if (!this.searchValue) return text;
const regex = new RegExp(`(${this.searchValue})`, "gi");
return text.replace(regex, `<span style="color: red;">$1</span>`);
}
}
};
</script>
3. 关键点解析:
-
搜索逻辑
- 遍历
treeData,找到匹配项及其父级节点。 - 只保留符合搜索条件的节点及路径上的所有父级节点。
- 遍历
-
高亮匹配文本
- 使用
v-html直接渲染高亮部分。 - 用正则表达式替换匹配部分,添加
span并改变颜色。
- 使用
-
自动展开搜索结果
- 记录搜索到的节点
key并赋值给expandedKeys,以展开相关节点。
- 记录搜索到的节点
效果:
- 输入关键词,树状结构自动筛选,并展开包含匹配项的所有父级节点。
- 匹配文本部分变红色高亮。
这个方案兼顾了搜索、匹配高亮、自动展开父级,符合 a-tree 组件的常见需求。 🚀