最近做项目经常会用到一些 UI 库,比如 element,iview 等,这些能够快速构建应用的库真的十分方便.比如 iview 的级联菜单很是好用,但是在使用的同时不免起了一些疑惑,它是怎么做到多级联动,依我所知,如果一个数据是多层的,我们就要多次使用 v-for,并且需要知道要循环几次,但是这个组件貌似不需要多次复用.好啦,下面进入正题!
数据
首先我们手里是一份这样的 JSON 数据:
子组件递归
list: [{
"id": "1",
"menuName": "项目管理",
"childTree": [{
"menuName": "项目进度",
"childTree": [{
"menuName": "项目一",
"childTree": [{
"menuName": "详细信息"
}]
}]
},
{
"menuName": "任务安排"
}]
},
{
"id": "2",
"menuName": "数据统计"
},
{
"id": "3",
"menuName": "人员管理"
}]
这是最重要的环节,组件的递归实现了级联菜单的多级联动,这个过程就如同实现对象的深复制一样.那么接下来我们按照这份数据写一个递归组件:
这里也有需要注意的,v-for 循环需要绑定 key,否则会报警告.
// 子组件代码
< template > <li > <span@click = "toggle" > {
{
model.menuName
}
} < /span>
<ul v-if="isFolder" v-show="open">
<items v-for="(item, index) in model.childTree" :model="item" :key="index"></items > </ul>
</li > </template>
<script type="text/javascript ">
export default {
// 组件递归必要条件,name属性
name: 'items',
props: ['model'],
data() {
return {
// 控制子列表的显示隐藏
open: false
}
},
computed: {
// 是否还有子列表需要渲染,作为v-if的判断条件
isFolder() {
return this.model.childTree && this.model.childTree.length
}
},
methods: {
// 切换列表显示隐藏的方法
toggle() {
if(this.isFolder) {
this.open = !this.open
}
},
}
}
</script>"
这里要强调以下,组件的 name 属性必须要有,否则无法实现递归,当然递归也需要有终止的条件,上边的 isFloder 便是了.
父组件调用
<template>
<div>
<ul>
<items v-for="(model, index) in list" :model="model" :key="index">
</items>
</ul>
</div>
</template>
<script type="text/javascript">
components: {
Items
},
data() {
return {
list: ...
}
}
</script>
最后来看下这个简单级联菜单的效果:
级联列表
来源: http://www.jianshu.com/p/c549c3d0f595