vue树形菜单实现
vue树形菜单实现方法
递归组件实现
使用Vue的递归组件特性可以轻松实现树形结构。定义一个组件,该组件能够调用自身来渲染子节点。
<template>
<ul>
<li v-for="item in treeData" :key="item.id">
{{ item.name }}
<tree-menu v-if="item.children" :treeData="item.children"></tree-menu>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeMenu',
props: {
treeData: Array
}
}
</script>
使用第三方库
对于复杂需求,可以使用成熟的树形组件库如vue-treeselect或element-ui的树形控件。
安装element-ui:
npm install element-ui
使用示例:
<template>
<el-tree :data="treeData" :props="defaultProps"></el-tree>
</template>
<script>
import { ElTree } from 'element-ui'
export default {
components: {
ElTree
},
data() {
return {
treeData: [{
label: '一级 1',
children: [{
label: '二级 1-1'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
}
}
}
</script>
动态加载数据
对于大型树结构,可以实现异步加载节点数据。
<template>
<el-tree
:props="props"
:load="loadNode"
lazy
></el-tree>
</template>
<script>
export default {
data() {
return {
props: {
label: 'name',
children: 'children',
isLeaf: 'leaf'
}
}
},
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ name: '根节点' }])
}
if (node.level > 3) return resolve([])
setTimeout(() => {
const data = Array.from({ length: 5 }).map((_, i) => ({
name: `节点${node.level}-${i}`,
leaf: node.level >= 3
}))
resolve(data)
}, 500)
}
}
}
</script>
自定义样式和交互
可以通过插槽自定义节点内容和样式。
<template>
<el-tree :data="data">
<template #default="{ node, data }">
<span class="custom-node">
<span>{{ node.label }}</span>
<span v-if="node.isLeaf" class="leaf-marker">✓</span>
</span>
</template>
</el-tree>
</template>
<style>
.custom-node {
padding: 0 8px;
}
.leaf-marker {
margin-left: 8px;
color: green;
}
</style>
完整示例代码
以下是一个完整的树形菜单实现示例:
<template>
<div class="tree-container">
<tree-node :node="treeData"></tree-node>
</div>
</template>
<script>
import TreeNode from './TreeNode.vue'
export default {
components: {
TreeNode
},
data() {
return {
treeData: {
id: 1,
name: '根节点',
children: [
{
id: 2,
name: '子节点1',
children: [
{ id: 4, name: '子节点1-1' },
{ id: 5, name: '子节点1-2' }
]
},
{
id: 3,
name: '子节点2',
children: [
{ id: 6, name: '子节点2-1' }
]
}
]
}
}
}
}
</script>
<style>
.tree-container {
padding: 20px;
}
</style>
TreeNode.vue组件:
<template>
<div>
<div @click="toggle" class="node">
<span v-if="hasChildren">{{ isOpen ? '-' : '+' }}</span>
{{ node.name }}
</div>
<div v-show="isOpen && hasChildren" class="children">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
></tree-node>
</div>
</div>
</template>
<script>
export default {
name: 'TreeNode',
props: {
node: Object
},
data() {
return {
isOpen: false
}
},
computed: {
hasChildren() {
return this.node.children && this.node.children.length
}
},
methods: {
toggle() {
if (this.hasChildren) {
this.isOpen = !this.isOpen
}
}
}
}
</script>
<style>
.node {
cursor: pointer;
padding: 5px 0;
}
.children {
padding-left: 20px;
}
</style>
这些方法涵盖了从简单到复杂的树形菜单实现方案,可以根据项目需求选择合适的实现方式。







