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

news2024/11/16 7:39:30

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

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>
  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>
  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>
  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.coloradmin.cn/o/1231819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

原理Redis-ZipList

ZipList 1) ZipList的组成2) ZipList的连锁更新问题3) 总结 1) ZipList的组成 ZipList 是一种特殊的“双端链表” &#xff0c;由一系列特殊编码的连续内存块组成。可以在任意一端进行压入/弹出操作, 并且该操作的时间复杂度为 O(1)。 ZipListEntry: ZipList 中的Entry并不像…

ClickHouse的 MaterializeMySQL引擎

1 概述 MySQL 的用户群体很大&#xff0c;为了能够增强数据的实时性&#xff0c;很多解决方案会利用 binlog 将数据写入到 ClickHouse。为了能够监听 binlog 事件&#xff0c;我们需要用到类似 canal 这样的第三方中间件&#xff0c;这无疑增加了系统的复杂度。 ClickHouse 20.…

数据结构--字符串的模式匹配

案例导入概念 朴素&#xff08;暴力&#xff09;模式匹配算法 定位操作&#xff1a; 计算时间复杂度 总结

如何使用Docker部署Apache+Superset数据平台并远程访问?

大数据可视化BI分析工具Apache Superset实现公网远程访问 文章目录 大数据可视化BI分析工具Apache Superset实现公网远程访问前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网…

go语言学习-go环境安装

1、安装Go 1.1 下载安装 go官网 找对应电脑的版本进行安装即可。 点击安装包&#xff0c;直接下一步下一步即可&#xff0c;安装目录可以自行设置一下。 1.2 验证 windows通过cmd验证。 linux或者mac可以通过自带终端执行测试。 2、配置环境变量 2.1 windows 找到系统…

基于安卓android微信小程序美容理发店预约系统app

项目介绍 为美容院设计一个系统以减少员工的工作量就成为了想法的初始状态。紧接着对美容院进行进一步的调查发现我的想法已然落后。基本上每个美容院都以有了自己的信息系统&#xff0c;并且做的已经较完善了。 在这时我突然想到&#xff0c;现在关注美容养生的人越来越多&am…

leetcode数据结构与算法刷题(三)

目录 第一题 交叉链表 思想&#xff1a; 注意点 第一步先求两个链表的长度 第二步 让长的先走&#xff0c;当长短一样时一起走。 犯错点 第二题 判断是有环 思想&#xff1a; 注意 错误分享 第三题&#xff08;重点面试题&#xff09; 思路&#xff1a; 这题面试问题&a…

复杂数据统计与R语言程序设计实验一

1.下载并安装R语言软件&#xff0c;熟悉基本操作的命令及操作界面&#xff0c;掌握软件的使用方法&#xff08;提供学号加姓名的截图&#xff09;。 2.下载并安装Rstudio&#xff0c; &#xff08;提供运行代码及运行结果的截图&#xff09;。 3.下载并安装R包DT&#xff0c;…

WordPress画廊插件Envira Gallery v1.9.7河蟹版下载

Envira Gallery是一款功能强大的WordPress画廊插件。通过使用这个插件&#xff0c;你可以在WordPress的前台页面上创建出令人赏心悦目的图片画廊展示形式。 拖放生成器&#xff1a;轻松创建精美照片和视频画廊 自定义主题&#xff0c;打造独特外观 使用预设模板&#xff0c;为…

代码随想录算法训练营第二十九天| 491 递增子序列 46 全排列

目录 491 递增子序列 46 全排列 491 递增子序列 在dfs中进行判断&#xff0c;如果path的长度大于1&#xff0c;则将其添加到res中。 本题nums中的元素的值处于-100与100之间&#xff0c;可以将元素映射0到199之间并且通过布尔数组st来记录此层中元素是否被使用过&#xff0c;…

使用树莓派学习Linux系统编程的 --- 库编程(面试重点)

在之前的Linux系统编程中&#xff0c;学习了文件的打开&#xff1b;关闭&#xff1b;读写&#xff1b;进程&#xff1b;线程等概念.... 本节补充“Linux库概念 & 相关编程”&#xff0c;这是一个面试的重点&#xff01; 分文件编程 在之前的学习中&#xff0c;面对较大的…

uniapp小程序定位;解决调试可以,发布不行的问题

遇见这个问题&#xff1b;一般情况就两种 1、域名配置问题&#xff1b; 2、隐私协议问题 当然&#xff0c;如果你的微信小程序定位接口没开启&#xff1b;定位也会有问题&#xff1b; 第一种&#xff0c;小程序一般是腾讯地图&#xff1b;所以一般都会用https://apis.map.qq.co…

AIGC ChatGPT4对Gbase数据库进行总结

ChatGPT4 用一个Prompt完成Gbase数据库的总结。 AIGC ChatGPT 职场案例 AI 绘画 与 短视频制作 PowerBI 商业智能 68集 数据库Mysql 8.0 54集 数据库Oracle 21C 142集 Office 2021实战应用 Python 数据分析实战&#xff0c; ETL Informatica 数据仓库案例实战 Excel 2021实操 …

基于AVR单片机的便携式心电监测设备设计与实现

基于AVR单片机的便携式心电监测设备是一种常用的医疗设备&#xff0c;用于随时监测和记录人体的心电信号。本文将介绍便携式心电监测设备的设计原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 设计概述 便携式心电监测设备是一种小巧、方便携带的设备&#xff0c;能够…

几个强力的nodejs库

几个强力的nodejs库 nodejs被视为许多Web开发人员的理想运行时环境。 nodejs的设计是为了在运行时中使用JavaScript编写的代码&#xff0c;它是世界上最流行的编程语言之一&#xff0c;并允许广泛的开发者社区构建服务器端应用程序。 nodejs提供了通过JavaScript库重用代码的…

微机原理_14

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1,下面寻址方式的操作数不在存储器中的是(&#xff09; A. 堆栈寻址 B. 寄存器间址 C.寄存器寻址 D. 直接寻址 2,条件转移指令JNE的条件是(&#xff09; A. CF…

EI论文程序:Adaboost-BP神经网络的回归预测算法,可作为深度学习对比预测模型,丰富实验内容,自带数据集,直接运行!

适用平台&#xff1a;Matlab 2021及以上 本程序参考中文EI期刊《基于Adaboost的BP神经网络改进算法在短期风速预测中的应用》&#xff0c;程序注释清晰&#xff0c;干货满满&#xff0c;下面对文章和程序做简要介绍。 为了提高短期风速预测的准确性&#xff0c;论文提出了使用…

Python-----PyInstaller的简单使用

PyInstaller简介 PyInstaller是一个Python库&#xff0c;可以将Python应用程序转换为独立的可执行文件。PyInstaller支持跨平台&#xff0c;可以在Windows、Linux和MacOS上生成可执行文件。 PyInstaller会分析Python程序&#xff0c;并将程序打包成一个完整的可执行文件&…

C练习题_14

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

ES6有何新特性?(下篇)

目录 函数参数的默认值设置 rest参数 扩展运算符 Symbol 迭代器 生成器 Promise Class 数值扩展 对象方法扩展 模块化 大家好呀&#xff01;今天这篇文章继续为大家介绍ES6的新特性&#xff0c;上上上篇文章介绍了一部分&#xff0c;这篇文章会将剩下的部分新增的特…