Tree 组件是递归类组件的典型表明,它经常使用于文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用树控件能够完整展示其中的层级关系,并具备展开收起选择等交互功能。
如图所示,咱们要实现的就是这样一个效果。以前咱们写树状结构都是用jQuery来实现的,用Vue怎么实现呢?vue
menuList:[
{
title:'菜单1',
children:[
{
title:'菜单1-1',
children:[
{title:'菜单1-1-1'},
{title:'菜单1-1-2'},
{title:'菜单1-1-3'}
]
},
{title:'菜单1-2'},
{title:'菜单1-3'}
]
},
{title:'菜单2'},
{title:'菜单3'}
]
复制代码
Menu.vuebash
首先咱们来写个menu组件,这里放个ul列表,里面的内容,用插槽来表示。
<template>
<ul>
<slot></slot>
</ul>
</template>
<script>
export default {
name: "Menu"
}
</script>
复制代码
MenuItem.vue架构
若是没有子节点,所要展现的标题
<template>
<li><slot></slot></li>
</template>
<script>
export default {
name: "MenuItem"
}
</script>
复制代码
SubMenu.vueapp
<template>
<div>
<div class="title" @click="change">
<slot name="title"></slot>
<!--name='title'区分插槽 -->
</div>
<div class="sub" v-show="flag">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "SubMenu",
data(){
return {flag:false}
},
methods:{
change(){
this.flag=!this.flag
}
}
}
</script>
<style>
.sub{
padding-left:20px;
}
</style>
复制代码
这里到了咱们实现树形结构思想的重点,即递归组件。当咱们重复判断有没有子节点,并作出相应的展现的时候,这里就可使用递归组件了。方便快捷,你值得拥有。ui
因为有子节点会循环SubMenu这部分操做,因此单独提出来放到ReSubMenu组件中
<template>
<SubMenu>
<template #title><!--#title为了标识区分插槽-->
{{data.title}}
</template>
<template v-for="child in data.children">
<MenuItem :key="child.title" v-if="!child.children">{{child.title}}</MenuItem>
<!--ReSubMenu跟name的名字保持一致,至关于循环使用该组件-->
<ReSubMenu v-else :key="child.title" :data="child"></ReSubMenu>
</template>
</SubMenu>
</template>
<script>
import SubMenu from './SubMenu'
import MenuItem from './MenuItem'
export default {
name: "ReSubMenu",//可使用递归组件
props:{
data:{
type:Object,//属性校验,为对象数据类型,而且若是没有赋值,默认给一个空对象
default:()=>({})
}
},
components:{
SubMenu,
MenuItem
}
}
</script>
复制代码
<div id="app">
<Menu>
<template v-for="menu in menuList">
<MenuItem :key="menu.title" v-if="!menu.children">{{menu.title}}</MenuItem>
<!--这部分是若是有孩子节点则会循环这部分操做,因此要单独提取出来-->
<!-- <SubMenu v-else>
<template #title>{{menu.title}}</template>
<template v-for="child in menu.children">
<MenuItem>{{child.title}}</MenuItem>
</template>
</SubMenu>-->
<ReSubMenu :key="menu.title" v-else :data="menu"></ReSubMenu>
</template>
</Menu>
<div>
<script>
import Menu from './Menu'
import MenuItem from './MenuItem'
// import SubMenu from './SubMenu'
import ReSubMenu from './ReSubMenu'
export default {
data(){
return{
//这里的数据我就模拟一个了
menuList:[
{
title:'菜单1',
children:[
{
title:'菜单1-1',
children:[
{title:'菜单1-1-1'},
{title:'菜单1-1-2'},
{title:'菜单1-1-3'}
]
},
{title:'菜单1-2'},
{title:'菜单1-3'}
]
},
{title:'菜单2'},
{title:'菜单3'}
]
}
},
components:{
Menu,MenuItem,ReSubMenu
}
}
</script>
复制代码
注:本节部分语句参考 https://juejin.im/book/5bc844166fb9a05cd676ebca/section/5bfcecc7f265da61682b102a
。this