Vue中的递归组件

  递归函数我们都再熟悉不过了,也就是函数自己调用自己。递归组件也是类似的,在组件的template内部使用组件自身。那递归组件有什么使用场景呢? 我们都知道树这个数据结构就是一种递归的结构,因此我们可以用递归组件去实现一个Tree效果,一般可以用于多层级的菜单。

首先是我们的Tree组件,它包含n个TreeNode(树的节点),也就是一级的菜单项。(注: treeData数据摘取自ElementUI的树形组件示例)

<template>
  <div id="app">
    <!-- 一级菜单列表-->
    <ul>
      <TreeNode v-for="nodeData in treeData" :nodeData="nodeData" :key="nodeData.label"></TreeNode>
    </ul>
  </div>
</template>
<script>
  import TreeNode from '../components/TreeNode'
  export default {
    name: 'Tree',
    components: { TreeNode },
    data () {
      return {
        treeData: [
          {
            label: '一级 1',
            children: [{
              label: '二级 1-1',
              children: [{
                label: '三级 1-1-1'
              }]
            }]
          }, {
            label: '一级 2',
            children: [{
              label: '二级 2-1',
              children: [{
                label: '三级 2-1-1'
              }]
            }, {
              label: '二级 2-2',
              children: [{
                label: '三级 2-2-1'
              }]
            }]
          }, {
            label: '一级 3',
            children: [{
              label: '二级 3-1',
              children: [{
                label: '三级 3-1-1'
              }]
            }, {
              label: '二级 3-2',
              children: [{
                label: '三级 3-2-1'
              }]
            }]
          }]
      }
    }
  }
</script>

然后我们来实现TreeNode组件。

<template>
  <li>
    <!-- 菜单项标题和展开/收起按钮-->
    <div>
      <span>{{nodeData.label}}</span>
      <span v-if="hasChild" @click="open = !open">[{{open ? '-' : '+'}}]</span>
    </div>
    <!-- 子菜单 -->
    <ul v-show="open" v-if="hasChild">
      <TreeNode v-for="childNodeData in nodeData.children" :nodeData="childNodeData" :key="childNodeData.label"></TreeNode>
    </ul>
  </li>
</template>
<script>
  export default {
    // 必须要写name, 否则在组件内部使用TreeNode标签将无法解析
    name: 'TreeNode',
    props: ['nodeData'],
    data: function () {
      return {
        // 标识展开/收起状态
        open: false
      }
    },
    computed: {
      // 是否有子菜单
      hasChild: function () {
        return this.nodeData.children && this.nodeData.children.length
      }
    }
  }
</script>
<style scoped>
  span {
    font-size: 36px;
  }
</style>

  我们都知道,一级菜单下面可能还包含多个二级菜单,二级菜单下面可能包含多个三级菜单,以此类推...因此,在TreeNode组件的template中我们再次使用了TreeNode组件,从而形成了递归组件。

运行效果如下,点击 + / - 号按钮可以实现展开和收起:

  

 

posted @ 2020-02-28 09:55  flamestudio  阅读(2828)  评论(0编辑  收藏  举报