vue中实现目录树
实现目录树的基本思路
在Vue中实现目录树通常需要递归组件来处理嵌套结构。目录树的数据通常是一个包含子节点的树形结构,每个节点可能有自己的子节点。
数据准备
准备一个树形结构的数据,例如:
const treeData = [
{
name: '节点1',
children: [
{
name: '节点1.1',
children: []
},
{
name: '节点1.2',
children: [
{
name: '节点1.2.1',
children: []
}
]
}
]
},
{
name: '节点2',
children: []
}
]
递归组件实现
创建一个递归组件TreeNode.vue:
<template>
<div class="tree-node">
<div @click="toggle">
{{ node.name }}
</div>
<div v-show="isOpen" v-if="node.children && node.children.length" class="children">
<TreeNode
v-for="child in node.children"
:key="child.name"
:node="child"
/>
</div>
</div>
</template>
<script>
export default {
name: 'TreeNode',
props: {
node: {
type: Object,
required: true
}
},
data() {
return {
isOpen: false
}
},
methods: {
toggle() {
this.isOpen = !this.isOpen
}
}
}
</script>
<style>
.tree-node {
margin-left: 20px;
cursor: pointer;
}
.children {
margin-left: 20px;
}
</style>
使用目录树组件
在主组件中使用这个递归组件:
<template>
<div class="tree-container">
<TreeNode
v-for="node in treeData"
:key="node.name"
:node="node"
/>
</div>
</template>
<script>
import TreeNode from './TreeNode.vue'
export default {
components: {
TreeNode
},
data() {
return {
treeData: [...] // 上面定义的treeData
}
}
}
</script>
添加交互功能
可以扩展功能,如:
- 添加选中状态
- 动态加载子节点
- 拖拽排序
- 搜索过滤
例如添加选中状态:
<template>
<div class="tree-node">
<div
@click="toggle"
:class="{ 'selected': isSelected }"
>
{{ node.name }}
</div>
<div v-show="isOpen" v-if="hasChildren" class="children">
<TreeNode
v-for="child in node.children"
:key="child.name"
:node="child"
@node-selected="onChildSelected"
/>
</div>
</div>
</template>
<script>
export default {
// ...
data() {
return {
isOpen: false,
isSelected: false
}
},
computed: {
hasChildren() {
return this.node.children && this.node.children.length
}
},
methods: {
toggle() {
this.isOpen = !this.isOpen
this.isSelected = !this.isSelected
this.$emit('node-selected', this.node)
},
onChildSelected(node) {
this.$emit('node-selected', node)
}
}
}
</script>
<style>
.selected {
background-color: #f0f0f0;
}
</style>
使用第三方库
如果需要更复杂的功能,可以考虑使用现成的Vue树形组件库:
vue-tree-halationvuejs-treeelement-ui的el-tree
例如使用element-ui的树组件:
<template>
<el-tree
:data="treeData"
:props="defaultProps"
@node-click="handleNodeClick"
/>
</template>
<script>
export default {
data() {
return {
treeData: [...],
defaultProps: {
children: 'children',
label: 'name'
}
}
},
methods: {
handleNodeClick(data) {
console.log(data)
}
}
}
</script>
性能优化
对于大型树结构,可以考虑:
- 虚拟滚动
- 懒加载子节点
- 扁平化数据结构处理
例如实现懒加载:
<template>
<div class="tree-node">
<div @click="loadChildren">
{{ node.name }}
<span v-if="loading">Loading...</span>
</div>
<div v-show="isOpen" v-if="hasChildren" class="children">
<TreeNode
v-for="child in node.children"
:key="child.id"
:node="child"
/>
</div>
</div>
</template>
<script>
export default {
// ...
data() {
return {
loading: false
}
},
methods: {
async loadChildren() {
if (!this.node.children || !this.node.children.length) {
this.loading = true
const children = await fetchChildren(this.node.id)
this.$set(this.node, 'children', children)
this.loading = false
}
this.isOpen = !this.isOpen
}
}
}
</script>






