vue实现tree组件查询
Vue实现Tree组件查询功能
基本Tree组件结构
需要先构建一个基础的Tree组件,包含节点渲染和展开/折叠功能。每个节点应包含label、children等属性。
<template>
<div class="tree">
<tree-node
v-for="node in filteredData"
:key="node.id"
:node="node"
@toggle="toggleNode"
/>
</div>
<input v-model="searchQuery" placeholder="搜索节点..." />
</template>
<script>
export default {
data() {
return {
treeData: [],
searchQuery: ''
}
},
computed: {
filteredData() {
if (!this.searchQuery) return this.treeData
return this.filterTree(this.treeData, this.searchQuery)
}
},
methods: {
filterTree(nodes, query) {
return nodes.filter(node => {
const match = node.label.includes(query)
if (match) return true
if (node.children) {
const filteredChildren = this.filterTree(node.children, query)
if (filteredChildren.length > 0) {
node.children = filteredChildren
return true
}
}
return false
})
},
toggleNode(node) {
node.expanded = !node.expanded
}
}
}
</script>
搜索功能实现
搜索功能需要递归遍历树结构,匹配节点名称并保留匹配节点的父级路径。
filterTree(nodes, query) {
const lowerQuery = query.toLowerCase()
return nodes.reduce((result, node) => {
const lowerLabel = node.label.toLowerCase()
const isMatch = lowerLabel.includes(lowerQuery)
let children = []
if (node.children) {
children = this.filterTree(node.children, query)
const hasMatchingChild = children.length > 0
}
if (isMatch || hasMatchingChild) {
const newNode = { ...node }
if (hasMatchingChild) {
newNode.children = children
}
result.push(newNode)
}
return result
}, [])
}
高亮匹配文本
在渲染节点时,对匹配的搜索文本进行高亮显示。
<template>
<div class="tree-node">
<div @click="toggle">
<span v-html="highlightText(node.label)"></span>
</div>
<div v-if="node.expanded && node.children">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
@toggle="$emit('toggle', $event)"
/>
</div>
</div>
</template>
<script>
export default {
props: ['node'],
methods: {
highlightText(text) {
if (!this.$parent.searchQuery) return text
const query = this.$parent.searchQuery
return text.replace(
new RegExp(query, 'gi'),
match => `<span class="highlight">${match}</span>`
)
},
toggle() {
this.$emit('toggle', this.node)
}
}
}
</script>
<style>
.highlight {
background-color: yellow;
font-weight: bold;
}
</style>
性能优化
对于大型树结构,需要优化搜索性能。
// 使用防抖减少频繁搜索带来的性能问题
import { debounce } from 'lodash'
export default {
data() {
return {
searchQuery: '',
debouncedFilter: null
}
},
created() {
this.debouncedFilter = debounce(this.doFilter, 300)
},
watch: {
searchQuery(newVal) {
this.debouncedFilter(newVal)
}
},
methods: {
doFilter(query) {
this.filteredData = this.filterTree(this.treeData, query)
}
}
}
完整组件示例
整合所有功能的完整Tree组件实现。
<template>
<div>
<input
v-model="searchQuery"
placeholder="搜索节点..."
class="search-input"
/>
<div class="tree-container">
<tree-node
v-for="node in filteredData"
:key="node.id"
:node="node"
:search-query="searchQuery"
@toggle="toggleNode"
/>
</div>
</div>
</template>
<script>
import TreeNode from './TreeNode.vue'
export default {
components: { TreeNode },
props: {
data: {
type: Array,
required: true
}
},
data() {
return {
searchQuery: '',
treeData: this.data
}
},
computed: {
filteredData() {
return this.searchQuery
? this.filterTree(this.treeData, this.searchQuery)
: this.treeData
}
},
methods: {
filterTree(nodes, query) {
// 实现同上
},
toggleNode(node) {
node.expanded = !node.expanded
this.$forceUpdate()
}
}
}
</script>
这些方法提供了在Vue中实现可搜索Tree组件的基本方案,可以根据实际需求进行调整和扩展。







