vue和uni-app的递归组件排坑

news/2023/12/1 11:23:30 标签: vue.js, uni-app, javascript

有这样一个数组数据,实际可能有很多级。

tree: [
  {
    id: 1,
    name: '1',
    children: [
      { 
        id: 2, 
        name: '1-1', 
        children: [
          {
            id: 7, 
            name: '1-1-1',
            children: []
          }
        ]
      },
      { id: 3, name: '1-2' }
    ]
  },
  {
    id: 4,
    name: '2',
    children: [
      { id: 5, name: '2-1' },
      { id: 6, name: '2-2' }
    ]
  }
]

要渲染为下面这种树形

应该很容易想到使用递归组件,下面就来写一个tree组件。简单用vue2实现一下。

用法很简单

传入tree数据,支持返回当前点击的节点。

实现一下

先写一个tree组件,在components/tree/index.vue

<template>
  <div>
    <div 
      class="node" 
      v-for="node in data" 
      :key="node.id"
    >
      <tree-node 
        :node="node" 
        @node-click="nodeClick"
      >
      </tree-node>
    </div>
  </div>
</template>

<script>javascript">
  import treeNode from './tree-node.vue'
  export default {
    components: { treeNode },
    props: {
      data: {
        type: Array,
        default: () => []
      }
    },
    methods: {
      nodeClick(node) {
        this.$emit('node-click', node)
      }
    }
  }
</script>

因为父组件页面中传进来的是个数组,需要先循环这个数组,然后递归渲染每一个子节点,我们就再写一个tree-node组件,专门用来渲染子节点,核心代码递归也是在这个组件中完成的。

同级目录写一个tree-node组件,在components/tree/tree-node.vue

<template>
  <div>
    <!-- 避免冒泡到父组件,要加.stop -->
    <div 
      class="node-name" 
      @click.stop="nodeClick"
    >
      {{node.name}}
    </div>
    <!-- 有children就遍历,递归渲染自身,把每一项传进去 -->
    <div 
      class="children" 
      v-if="node.children && node.children.length"
    >
      <tree-node 
        v-for="item in node.children" 
        :key="item.id" 
        :node="item" 
        v-on="$listeners"
      >
      </tree-node>
    </div>
  </div>
</template>

<script>javascript">
  export default {
    name: 'tree-node',
    props: {
      node: Object
    },
    methods: {
      nodeClick() {
        // 因为传入当前组件的是每一级的节点
        // 只需要再传回去就好了
        this.$emit('node-click', this.node)
      }
    }
  }
</script>

<style scoped>
  .node-name {
    cursor: pointer;
  }
  .children {
    padding-left: 20px;
  }
</style>

划重点、抛出问题

  1. 递归的核心是自己调用自己,但要注意边界条件,否则会进入死循环,内存泄漏。对应到以上代码就是v-if="node.children && node.children.length"
  2. 以上代码已经实现了递归渲染,但只是vue2的实现。你可能注意到其中有一个很重要的语句,v-on="$listeners",如果不加会导致从第二层递归开始直到最底层,都无法使用emit向父组件传递事件,因为每一级节点的父组件都是自身,需要传给子组件一个事件,子组件才能使用emit调用。
那么还有其他方式解决以上问题吗

这就不得不说说uni-appvue3了,顺便也说说uni-appvue在递归组件这方面的不同点。

  1. uni-app不支持$listeners,vue3也移除了$listeners,那如何解决呢?下面是不使用$listeners的做法,在v2、uni-app和v3中都适用,无非是v3使用了组合式api。注意看注释,有三个改动点
<template>
  <div>
    <!-- 改动点1,当前节点数据通过点击事件传递 -->
    <div 
      class="node-name" 
      @click.stop="nodeClick(node)"
    >
      {{node.name}}
    </div>
    <div 
      class="children" 
      v-if="node.children && node.children.length"
    >
      <!-- 
        核心:改动点2,
        不再使用$listeners,
        每一级都传递一次node-click,
        使用nodeClick方法接收参数
      -->
      <tree-node 
        v-for="item in node.children" 
        :key="item.id" 
        :node="item" 
        @node-click="nodeClick"
      >
      </tree-node>
    </div>
  </div>
</template>

<script>javascript">
  export default {
    name: 'tree-node',
    props: {
      node: Object
    },
    methods: {
      // 改动点3,通过参数接收数据
      nodeClick(node) {
        this.$emit('node-click', node)
      }
    }
  }
</script>

<style scoped>
  .node-name {
    cursor: pointer;
  }
  .children {
    padding-left: 20px;
  }
</style>
  1. 在vue中使用递归组件,无论v2还是v3,都只需要设置一个name属性,即可直接调用,在uni-app中除了设置name属性,还需要使用import引入自身,并使用components注册组件。
// 引入自身
import treeNode from './tree-node.vue'
export default {
  name: 'tree',
  components: { treeNode },
  props: {
    node: Object
  },
  methods: {
    
  },
}

http://www.niftyadmin.cn/n/5198840.html

相关文章

C练习题_14

一、单项选择题&#xff08;本大题共 20小题&#xff0c;每小题 2分&#xff0c;共 40分。在每小题给出的四个备选项中&#xff0c;选出一个正确的答案&#xff0c;并将所选项前的字母填写在答题纸的相应位置上。) 以下叙述不正确的是&#xff08;&#xff09; A.一个C源程序可…

Springboot和Vue+MYSQL项目(基本介绍+前后端结合初步项目)+maven+mybatis

一、基本知识 当我们谈论全栈开发时&#xff0c;通常指的是一个开发者能够处理整个应用程序的开发&#xff0c;包括前端&#xff08;Front-End&#xff09;和后端&#xff08;Back-End&#xff09;的所有层面。这三个基本的领域是&#xff1a; 前端开发&#xff08;Front-End …

MobaXterm如何连接CentOS7的Linux虚拟机?Redis可视化客户端工具如何连接Linux版Redis?

一、打开Lunix虚拟机,进入虚拟机中,在终端中输入ifconfig,得到以下信息&#xff0c;红框中为ip地址 二、打开MobaXterm&#xff0c;点击session 选择SSH&#xff0c;在Remote host中输入linux得到的IP地址&#xff0c;Specify username中可起一个任意的连接名称。 输入密码 四、…

集合的自反关系和对称关系

集合的自反关系和对称关系 一&#xff1a;集合的自反关系1&#xff1a;原理&#xff1a;2&#xff1a;代码实现 二&#xff1a;对称关系1&#xff1a;原理&#xff1a;2&#xff1a;代码实现 三&#xff1a;总结 一&#xff1a;集合的自反关系 1&#xff1a;原理&#xff1a; …

【前端学java】Java中的接口和枚举概念(7)

theme: smartblue 往期回顾&#xff1a; 【前端学java】JAVA开发的依赖安装与环境配置 &#xff08;0&#xff09;【前端学 java】java的基础语法&#xff08;1&#xff09;【前端学java】JAVA中的packge与import&#xff08;2&#xff09;【前端学java】面向对象编程基础-类…

请求的接口响应状态为已取消的原因

有趣的iframe问题 今天遇到一个问题&#xff0c;当点击了按钮----跳转页面时----F12键点击网络中的状态报了已取消&#xff0c;类型是 document说明是前端页面的问题&#xff0c;如果是xhr那可能是接口的问题。 原本是写了3个iframe,页面刷新的时候请求了第一个iframe,然后就…

【ceph】ceph集群的故障域是怎么快速修改导入导出

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

Stable Diffusion 秋葉aaaki整合包远程访问设置

Stable Diffusion 秋葉aaaki整合包远程访问设置 0. 背景1. 解决方法 12. 解决方法 2 0. 背景 在局域网的一台服务器上安装了秋葉aaaki整合包&#xff0c;实现局域网内其他机器访问这台服务器上启动的 Stable Diffusion Web UI&#xff0c;但是默认的启动 server_name 是 127.0…

P1281 书的复制

P1281 书的复制 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 书按顺序给k个人&#xff0c;进行抄写&#xff0c;求抄写页数最多的人所用的时间的最小值。最大值最小&#xff0c;考虑二分。 又因为题目要求要尽可能让前面的人少抄写&#xff0c;那么就要求后面的多抄写&…

分布式与微服务 —— 初始

前言 距今微服务的提出已经过去快十个春秋&#xff0c;网络上的博文讲微服务也是一抓一大把&#xff0c;但是荔枝仍然觉得还是有必要自己梳理一下整个知识体系。在这篇文章中&#xff0c;荔枝将会以一个初学者的角度来切入&#xff0c;从分布式系统和微服务架构引入&#xff0c…

华为OD机试 - 机器人搬砖(Java JS Python C)

目录 题目描述 输入描述 输出描述 用例 题目解析 JavaScript算法源码 Java算法源码

LangChain 5易速鲜花内部问答系统

展示了一个完整的问答系统的实现&#xff0c;使用了Flask来构建Web界面、langchain进行文档处理和检索&#xff0c;以及OpenAI的语言模型。代码的复杂性在于集成了多种高级技术和处理大型数据集和语言模型。 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt t…

Visio免费版!Visio国产平替软件,终于被我找到啦!

作为一个职场人士&#xff0c;我经常需要绘制各种流程图和图表&#xff0c;而Visio一直是我使用的首选工具。但是&#xff0c;随着公司的发展和工作的需要&#xff0c;我逐渐发现了Visio的优点和不足。 首先&#xff0c;让我们来看看Visio的优点。Visio是一个专业的流程图和图…

odoo16 一个比较复杂的domain

一个比较复杂的domain 今天在做项目管理的二开&#xff0c;碰到一个比较复杂的domain domain"[(user_ids, in, uid),(state, in, (已发布,进行中,待审核))]"domain"[&amp;,|,(user_ids, in, uid),(last_task_user_ids, in, uid),(state, , 待审核)]"需…

C语言的5个内存段你了解吗?( 代码段/数据段/栈/堆)

前言&#xff1a;这些内存段在程序运行时起着不同的作用&#xff0c;有不同的分配方式和存储内容。对于 C 语言程序员来说&#xff0c;了解这些内存段的特性和用途有助于更好地理解内存管理、变量的存储位置以及程序执行过程中的内存分配情况 1. 代码段 (Code Segment) 内容&a…

【小呆的力学笔记】有限元专题之循环对称结构有限元原理

文章目录 1. 循环对称问题的提出2. 循环对称条件2.1 节点位移的循环对称关系2.2 节点内力的循环对称关系 3. 在平衡方程中引入循环对称条件 1. 循环对称问题的提出 许多工程结构都是其中某一扇面的n次周向重复&#xff0c;也就是是周期循环对称结构。如果弹性体的几何形状、约…
最新文章