vue递归组件 (树形控件 )

Posted dachengzizi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue递归组件 (树形控件 )相关的知识,希望对你有一定的参考价值。

  首先我们要知道,既然是递归组件,那么一定要有一个结束的条件,否则就会使用组件循环引用,最终出现“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>

以上是关于vue递归组件 (树形控件 )的主要内容,如果未能解决你的问题,请参考以下文章

vue+element tree(树形控件)组件

Vue.js怎样把递归组件构建为树形菜单

Vue组件的高级用法

vue递归组件—开发树形组件Tree--(构建树形菜单)

vue2 递归组件--树形学习分享

vue+elemenUi+menu实现树形导航栏递归组件目录菜单menuforEachMathfloorrandom