vue递归组件 (树形控件 )

时间:2024-08-19 19:35:50

  首先我们要知道,既然是递归组件,那么一定要有一个结束的条件,否则就会使用组件循环引用,最终出现“max stack size exceeded”的错误,也就是栈溢出。那么,我们可以使用v-if="判断条件"作为递归组件的结束条件。当遇到v-if为false时,组件将不会再进行渲染

1. 准备一个树状的递归数据  这里演示一个侧边栏组件

navigation: [
{
types: 1,
id: "0",
name: "首页",
path: "/jiaowu_system/home",
icon: "icon_hrIndex.png",
children: []
},
{
types: 1,
id: "1",
name: "教学资源",
path: "",
icon: "jiaowu_system_jiaoxueziyuan.png",
children: [
{
types: 2,
id: "1 - 1",
name: "学校信息",
path: "/jiaowu_system/SchoolInformation",
icon: "",
children: []
},
{
types: 2,
id: "1 - 2",
name: "管理部门信息",
path: "/jiaowu_system/administration",
icon: "",
children: []
}
]
},
{
types: 1,
id: "2",
name: "教学计划",
path: "",
icon: "jiaowu_system_jihua.png",
children: []
}
]

2. 创建一个简单的递归组件 

 // 这里 我是通过name实现递归效果的 你可以把它当作从import导入了一个组件并注册,我们在temlpate可以使用<list-menu></list-menu>使用子组件自身进行递归了   默认不展示子组件,只能在父组件点击的时候才会展示 使用的 v-show  减少渲染消耗

<template>
<div class="list">
<div @click.prevent="handleClick">
{{ model.name }}
</div>
<div v-show="reveal" v-if="isDispaly" style="margin-left:20px;">
<list-menu v-for="item in model.children" :key="item.id" :model="item" />
</div>
</div>
</template> <script>
export default {
name: "listMenu",
components: {},
props: ["model"],
data() {
return {
reveal: false
};
},
methods: {
handleClick() {
if (this.isDispaly) {
this.reveal = !this.reveal;
}
}
},
computed: {
isDispaly() {
return this.model.children && this.model.children.length;
}
}
};
</script> <style scoped>
div {
width: 100px;
margin: 20px 0;
}
</style>

上述代码中我们需要注意,这个组件必须含有 name 这个属性,因为没有 name 这个属性会造成控件自身不能调用自身, 当使用它时,只需要把上边我们定义好的数据通过props的方式传进去即可

3. 我们创建一个sidebar组件,这个组件作为使用递归组件的父组件 

  // navigation的数据在上面 需要copy

<template>
<div class="sidebar">
<div v-for="menu in navigation" :key="menu.id">
<list-menu :model="menu"></list-menu>
</div>
</div>
</template> <script>
import listMenu from "./list";
export default {
name: "sidebar",
components: {
listMenu
},
props: {},
data() {
return {
navigation: [] // 数据太长 就不在这里面写了
};
}
};
</script>

  好了 我们就实现了一个简单的递归侧边栏组件,这段代码只是简单的做了下递归组件的使用。对于折叠树状菜单来说,我们一般只会去渲染一级的数据,当点击一级菜单时,再去渲染一级菜单下的结构,如此往复。那么v-if就可以实现我们的这个需求,当v-if设置为false时,递归组件将不会再进行渲染,设置为true时,继续渲染。组件中的name不仅可以递归的时候使用 还可以当项目使用keep-alive时,可搭配组件name进行缓存过滤

一个简单的小实例

<div id="app">
<keep-alive exclude="Detail">
<router-view/>
</keep-alive>
</div>