前言
在实际生活中经常会遇到树状列表,这里我们试着自己动手实现一个Tree树形组件。
主要思想
对Vue组件使用递归,判断节点是否包含子节点,若包含则对组件进行递归。
开发环境及开发工具
- 开发工具:VS Code;
- 框架:Vue
- 图标库:Font Awesome
具体代码
<div id="app">
<sb-tree :data="list1"></sb-tree>
<sb-tree :data="list2" :keys="keys"></sb-tree>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('sb-tree', {
props: {
data: {
type: Array,
required: true
},
keys: {
type: Object,
validator: function(val) {
let keys = Object.keys(val);
return keys.includes('label')&&keys.includes('children');
},
default () {
return {
label: 'label',
children: 'children'
}
}
}
},
data() {
return {
mylist: this.data.map(r=>{
return {
label: r[this.keys.label],
children: r[this.keys.children],
isShow: false
}
})
}
},
// 版本2,可自定义数组属性名
template: `
<ul>
<li v-for="item in mylist" style="margin:10px;list-style:none;">
<i class="fa" aria-hidden="true" v-if="item.children&&item.children.length" :class="item.isShow?'fa-angle-down':'fa-angle-right'"></i>
<span @click="item.isShow=!item.isShow">{{item.label}}</span>
<sb-tree style="padding:5px" v-show="item.isShow" :keys="keys" v-if="item.children&&item.children.length" :data="item.children"></sb-tree>
</li>
</ul>
`,
// 版本1,数组属性名必须为label和children
// template: `
// <ul>
// <li v-for="item in data">
// {{item.label}}
// <sb-tree v-if="item.children&&item.children.length" :data="item.children"></sb-tree>
// </li>
// </ul>
// `,
})
new Vue({
el: "#app",
data() {
return {
keys: {
label: 'name',
children: 'cc'
},
list2: [{
name: 'A',
cc: [{
name: 'A-1',
cc: [{
name: 'A-1-1',
cc: [{
name: 'A-1-1-1',
cc: []
}]
}, ]
}]
},
{
name: 'B',
cc: [{
name: 'B-1',
cc: []
}]
},
],
list1: [{
label: 'A',
children: [{
label: 'A-1',
children: []
},
{
label: 'A-2',
children: [{
label: 'A-2-1',
children: []
}, ]
},
]
},
{
label: 'B',
children: []
},
{
label: 'C',
children: []
},
],
}
},
methods: {
},
})
</script>
组件sb-tree需要数据作为参数,这里利用props将data作为必须的属性,keys作为可选属性。
keys的作用是让调用者可以自由定义组件的节点名和子节点名。比如本例中list1的label和children。list2中就使用了自定义属性名name和cc。
为了不改动原数据,在组件中使用mylist将原数据拷贝并处理,并添加一个isShow属性用来显示或隐藏子节点。
效果如下图:

点击节点时,会触发click事件,若isShow为false会将isShow取反并显示子节点,反之,若isShow为true则会将isShow取反为false并隐藏子节点。