vue—递归组件(vue组件name的作用之一)

vue—递归组件(vue组件name的作用之一)

相信我们对递归不陌生,因为它是算法中很常见解决问题的思想。而在这里我先强调一点,递归最重要的是什么?终止条件,一个递归不能没有终止条件。

有时候我们在项目中,可能会遇一种需求,它要求我们把很深层嵌套的json数据渲染到页面中,比如文件目录结构。现在我们就把一个文件夹下的所有文件模拟渲染到页面中。
文件目录的树形结构:
文件目录的树形结构

为什么要使用递归?

可能有人会有疑惑,我们为什么要使用递归,使用多个v-for嵌套渲染数据不行吗?
首先我们要搞清楚这几点:

  1. 数据是灵活的,我们并不知道它嵌套有多少层
  2. 如果数据特别庞大,我们需要写多少代码呢?

所以,想要解决以上问题,在vue中使用递归组件无疑是一种很好的选择

vue递归组件

前边对需求分析了很多,那到底什么是递归组件,说白了我们可以把组件当作函数,在组件内部自己调用自己就行了。我们完全可以把它当成使用递归遍历树结构。

1. 首先我们先看一下我们的数据吧
files: {
        title: "我的文件",
        children: [{
            {
            title: "学习",
            children: [
            {
                title: "大学英语"
            },{
                title: "高等数学"
            },{
                title: "计算机",
                children: [{
                    title: "计算机操作系统"
                  },{
                    title: "计算机网络"
                  },{
                    title: "计算机组成原理"
                  }
                ]
            }
         }]
      }

这里我没有放太多,看一下格式和结构就行了。我们就是要把这些深层嵌套的数据渲染到页面中。

2. 主函数(主组件)

我们就像递归程序一样,首先需要注册一个主组件,在主组件中存放数据调用递归组件,并将数据传递给需要递归的子组件

<template>
  <ul id="main">	// 将子组件写进ul内是因为子组件根元素是li
    <tree :files="files"></tree>	// files就是我们的数据
  </ul>
</template>

将子组件写进ul内是因为子组件根元素是li
files就是我们的数据

3. 递归函数(子组件)
<template>
  <li v-if="files">	// 因为需要递归,根元素必须是li
    <section @click="openFile">	// openFile点击方法
      <span>{{files.title}}</span>	// 文件标题
      <span class="files-mark" v-if="isShow && files.children">-</span>
      <span class="files-mark" v-else-if="files.children">+</span>	// 展开图标显示
    </section>
    <ul v-if="isShow">	// 重点!! isshow数据作用是判断是否展开文件,通过openFile方法改变
      <tree v-for="(item, index) in files.children" :key="index" :files="item"> //这里的v-for循环遍历的子文件数据,递归调用自身,同时他也是终止条件,如果files.children不存在,就不会调用自身 :files="item"传递参数
      </tree>
    </ul>
  </li>
</template>
  1. 因为需要递归,根元素必须是li
  2. 这里的v-for循环遍历的子文件数据,递归调用自身
  3. 同时v-for也是终止条件,如果files.children不存在,v-for循环截至,就不会调用自身
  4. :files="item"传递参数给下一层组件

递归组件大致结构和原理就是这样,最后还有一个很重要的细节
子组件一定要有name属性!,递归调用自身是通过name属性,当作组件标签名字调用的,如果没有这个属性,无法调用自身。而且最好将name属性首字母大写。

export default {
  name: "Tree",	 // 关键点
  data() {
    return {
      isShow: false	// 控制是否展开
    }
  },
  methods: {
    openFile(){
      this.isShow = !this.isShow;	// 展开或者关闭
    }
  },
  props: {	// 接受父组件传递的参数
    files: {
      type: Object,
      required: true
    }
  }
}

版权声明:本文为qq_42586895原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。