vue递归组件,认识树形组件基础原理,纯数据驱动组件

32 篇文章 2 订阅

背景

1、个人心血来潮想试试如何实现无限嵌套组件,也就是当数据不确定的情况下,如何渲染组件

2、自我思考以后肯定会需要用到这种思维和开发方式,早点学,早点掌握

3、好奇之前jqui的文件夹列表实现

说明:

组件写的很垃圾,很丑,大家请关注原理实现

开始实现

第一步思考

首先既然是树形渲染,那么for循环是肯定需要的,

问题:

for循环的时候只能单列循环,也确实是数据驱动,但是当数据是层层嵌套该怎么办呢?两个for循环?但是想想也不现实啊

第二步思考

通过百度得知,所有无限嵌套都是利用了递归算法

那vue如何实现呢?我最后从vuejs官方得到了这段话

组件在渲染树中互为对方的后代祖先 地址:https://cn.vuejs.org/v2/guide/components-edge-cases.html#递归组件

具体我就不多说了,vue的官方例子有说明原理也讲述清楚了,只是没有完整的实例,那么下面就是自己来实现这个实例了

第三步实现

数据一次

首先你的数据一开始是这样的

menus2: [
        {
          text: "水果1"
        },
        {
          text: "苹果1"
        },
        {
          text: "橘子1"
        }
      ]

那么我就先for循环出第一组数据得到

数据二次

现在后端说我的菜单会多一层数据,数据变成这样的

menus2: [
        {
          text: "水果1",
          children: [
            {
              text: "香蕉2"
            }
          ]
        },
        {
          text: "苹果1",
          children: [
            {
              text: "木瓜2"
            }
          ]
        },
        {
          text: "橘子1",
          children: [
            {
              text: "百香2"
            }
          ]
        }
      ]

实现也是很简单,我可以for循环一次,再内嵌一次就ok了,但是记住vue官方的话,递归组件在于组件相互调用互为父子关系,

那么我就写一个专门循环子数据的组件,然后放进来

外层for循环代码:

  <ul>
    <li v-for="(item, index) in menus2" :key="index">
      <div class="one">
        {{ item.text }}
      </div>
      <div v-if="item.children && item.children.length > 0">
        <tree-ul :node="item.children"></tree-ul>
      </div>
    </li>
  </ul>

内部子组件代码,去循环数据的二层结构

<div class="twoli">
    <template v-for="(item, index) in node">
      <div class="two" :key="index">{{ item.text }}</div>
      <template v-if="item.children && item.children.length > 0">
        <tree-li :key="index" :node="item.children"></tree-li>
      </template>
    </template>
  </div>

注意代码结构,其实是一个单纯的for循环,这样我就得到了得到了二层循环数据

页面效果

第三次数据变化

数据:

menus2: [
        {
          text: "水果1",
          children: [
            {
              text: "香蕉2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        },
        {
          text: "苹果1",
          children: [
            {
              text: "木瓜2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        },
        {
          text: "橘子1",
          children: [
            {
              text: "百香2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        }
      ]

可以看到数据变成了三层结构

一样,按上一次的原理,我再写一个组件去循环第三层数据

<div class="sanli">
    <template v-for="(item, index) in node">
      <div class="san" :key="index">{{ item.text }}</div>
      <template v-if="item.children && item.children.length > 0">
        <tree-ul :key="index" :node="item.children"></tree-ul>
      </template>
    </template>
  </div>

这时候效果

可以看到都已经循环出来了

第四次数据变化

数结构

menus2: [
        {
          text: "水果1",
          children: [
            {
              text: "香蕉2",
              children: [
                {
                  text: "芒果3",
                  children: [
                    {
                      text: "李子4"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          text: "苹果1",
          children: [
            {
              text: "木瓜2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        },
        {
          text: "橘子1",
          children: [
            {
              text: "百香2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        }
      ]

这时候看到数据已经到了第四层,其实我上面的代码已经把互相嵌套的部分写完了

回顾两次内部组件代码

组件名称分别是:

tree-ul,tree-li

我上面贴代码的时候其实偷懒了,把后面的代码提前写好了

tree-ul代码调用了tree-li组件去循环上层传递过来的数据,然后如果发现有子层级,则传递给tree-li组件

  <div class="twoli">
    <template v-for="(item, index) in node">
      <div class="two" :key="index">{{ item.text }}</div>
      <template v-if="item.children && item.children.length > 0">
        <tree-li :key="index" :node="item.children"></tree-li>
      </template>
    </template>
  </div>

tree-li代码获取上层传递过来的数据,如果发生子层级,传递给tree-ul组件

  <div class="sanli">
    <template v-for="(item, index) in node">
      <div class="san" :key="index">{{ item.text }}</div>
      <template v-if="item.children && item.children.length > 0">
        <tree-ul :key="index" :node="item.children"></tree-ul>
      </template>
    </template>
  </div>

最后大家发现,两个组件之间代码基本上一模一样,但是主要是互相调用了一遍。因为vue组件不可能自己调用自己,那么可以用这样的方式实现递归调用,

递归算法原理:自己调用自己

然后讲一下vue官方注意的地方,两个组件注册不能用同步注册方式,

必须是全局注册,或者内部异步注册

我这里是这样的内部注册方式

components: {
  treeUl: () => {
    return import("./tree.vue");
  }
}

最后效果图,第四层级也出来了

我再加一层数据,有五层

再加那么再有,我可以无限的子嵌套下去。

数据部分:

menus2: [
        {
          text: "水果1",
          children: [
            {
              text: "香蕉2",
              children: [
                {
                  text: "芒果3",
                  children: [
                    {
                      text: "李子4",
                      children: [
                        {
                          text: "葡萄5"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          text: "苹果1",
          children: [
            {
              text: "木瓜2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        },
        {
          text: "橘子1",
          children: [
            {
              text: "百香2",
              children: [
                {
                  text: "芒果3"
                }
              ]
            }
          ]
        }
      ]

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值