vue实现树形控件搜索
Vue 树形控件搜索实现方法
基础树形结构实现
使用 el-tree 组件构建基础树形结构,需设置 node-key 和 props 配置项:
<template>
<el-tree
:data="treeData"
:props="defaultProps"
node-key="id"
ref="tree"
></el-tree>
</template>
<script>
export default {
data() {
return {
treeData: [
{ id: 1, label: '一级节点', children: [...] }
],
defaultProps: {
children: 'children',
label: 'label'
}
}
}
}
</script>
实现搜索功能
添加搜索输入框并绑定过滤方法:

<template>
<div>
<el-input v-model="filterText" placeholder="输入关键字过滤"></el-input>
<el-tree
:data="filteredTree"
:filter-node-method="filterNode"
ref="tree"
></el-tree>
</div>
</template>
<script>
export default {
data() {
return {
filterText: '',
originalTree: [...], // 原始数据备份
}
},
computed: {
filteredTree() {
return this.filterTree(this.originalTree, this.filterText)
}
},
methods: {
filterTree(nodes, keyword) {
if (!keyword) return nodes
return nodes.filter(node => {
const match = node.label.includes(keyword)
if (node.children) {
node.children = this.filterTree(node.children, keyword)
return match || node.children.length > 0
}
return match
})
}
}
}
</script>
性能优化方案
对于大型树结构,建议采用以下优化:
-
添加防抖处理搜索输入

watch: { filterText: { handler: _.debounce(function(val) { this.$refs.tree.filter(val) }, 500) } } -
使用虚拟滚动优化渲染性能
<el-tree-virtual :data="treeData" :item-size="32" height="500px" ></el-tree-virtual>
高亮显示匹配项
在树节点中使用插槽实现搜索词高亮:
<el-tree :data="treeData">
<template #default="{ node, data }">
<span v-html="highlight(node.label, filterText)"></span>
</template>
</el-tree>
methods: {
highlight(text, keyword) {
if (!keyword) return text
const reg = new RegExp(keyword, 'gi')
return text.replace(reg, match => `<span style="color: red">${match}</span>`)
}
}
完整组件示例
<template>
<div class="tree-search-container">
<el-input
v-model="filterText"
placeholder="输入搜索内容"
clearable
/>
<el-tree
ref="treeRef"
:data="filteredData"
:props="defaultProps"
:filter-node-method="filterNode"
default-expand-all
/>
</div>
</template>
<script>
export default {
data() {
return {
filterText: '',
defaultProps: {
children: 'children',
label: 'label'
},
treeData: [
// 树形数据
]
}
},
computed: {
filteredData() {
return this.filterTree([...this.treeData], this.filterText)
}
},
methods: {
filterTree(nodes, keyword) {
if (!keyword) return nodes
return nodes.filter(node => {
const match = node.label.toLowerCase().includes(keyword.toLowerCase())
if (node.children) {
node.children = this.filterTree(node.children, keyword)
return match || node.children.length > 0
}
return match
})
},
filterNode(value, data) {
if (!value) return true
return data.label.toLowerCase().includes(value.toLowerCase())
}
}
}
</script>






