树形结构,大多都采用递归组件完成
TreeView.vue
<template>
<div class="container">
<h4>Vue.js可扩展树菜单(递归组件)</h4>
<tree-menu :nodes="tree.nodes" :depth="0" :label="tree.label"></tree-menu>
</div>
</template>
<script>
import TreeMenu from "./TreeMenu";
let tree = {
label: "root",
nodes: [
{
label: "item1",
nodes: [
{
label: "item1.1"
},
{
label: "item1.2",
nodes: [
{
label: "item1.2.1"
}
]
}
]
},
{
label: "item2"
}
]
};
export default {
components: {
TreeMenu
},
data() {
return {tree}
}
};
</script>
<style scoped>
.container {
width: 300px;
margin: 0 auto;
text-align: left;
}
</style>
TreeMenu.vue
<template>
<div class="tree-menu">
<div class="label-wrapper" @click="toggleChildren">
<div :style="indent" :class="labelClasses">{{ label }}</div>
</div>
<template v-if="showChildren">
<TreeMenu
v-for="node in nodes"
:key="node.label"
:nodes="node.nodes"
:label="node.label"
:depth="depth + 1"
></TreeMenu>
</template>
</div>
</template>
<script>
export default {
name: "TreeMenu",
props: ["nodes", "label", "depth"],
data() {
return {
showChildren: true
};
},
computed: {
labelClasses() {
return { "has-children": this.nodes };
},
indent() {
return { transform: `translate(${this.depth * 30}px)` };
}
},
methods: {
toggleChildren() {
this.showChildren = !this.showChildren;
}
}
};
</script>
<style scoped>
.tree-menu .label-wrapper {
padding: 10px 0;
border-bottom: 1px solid #ccc;
text-align: left;
}
.tree-menu .label-wrapper .has-children {
cursor: pointer;
}
</style>