vue递归组件 (树形控件 )
大橙爱吃大橙子 人气:0首先我们要知道,既然是递归组件,那么一定要有一个结束的条件,否则就会使用组件循环引用,最终出现“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: 2, id: "1 - 3", name: "专业信息", path: "/jiaowu_system/Ammatilliset", icon: "", children: [] }, { types: 2, id: "1 - 4", name: "教学场地信息", path: "/jiaowu_system/classroom", icon: "", children: [] } ] }, { types: 1, id: "2", name: "教学计划", path: "", icon: "jiaowu_system_jihua.png", children: [ { types: 2, id: "2 - 1", name: "课程环节/管理", path: "/jiaowu_system/CoursePractice", icon: "", children: [] }, { types: 2, id: "2 - 2", name: "设置教学计划", path: "", icon: "", children: [ { types: 3, id: "2 - 1 - 1", name: "设置培养方案", path: "/jiaowu_system/trainingPlan", icon: "", children: [] }, { types: 3, id: "2 - 1 - 2", name: "复制培养方案", path: "/jiaowu_system/copyTrainingPlan", icon: "", children: [] } ] }, { types: 2, id: "2 - 3", name: "核定教学计划", path: "/jiaowu_system/ensure_plan", icon: "", children: [] }, { types: 2, id: "2 - 4", name: "查看教学计划", path: "/jiaowu_system/teachingResources", icon: "", 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>
加载全部内容