当前位置: 首页 > article >正文

vue3递归组件---树形组件

第一种方式,直接自己调用自己

Tree.vue

<template>
  <div class="tree">
    <div v-for="(item, index) in data" :key="item.name">
      每一层 {{ item.name }}
      <Tree v-if="item?.children?.length" :data='item.children' />
    </div>
  </div>
</template>

<script setup lang="ts">
//递归的第一种方式 直接引入自己
import Tree from './Tree.vue'
import { TreeList } from '../ts/type'
type Props = {
  data?: TreeList[]
}
defineProps<Props>();
</script>

<style scoped>
.tree {
  margin-left: 20px;
  border-left: 2px #01847f dashed;
}
</style>

App.vue 里模拟树形数据,使用递归组件

<template>
  <div>
    <Tree :data='data'/>
  </div>
</template>

<script setup lang="ts">
import Tree from './components/Tree.vue'
import { reactive } from 'vue'
import {TreeList } from './ts/type'
const data = reactive<TreeList[]>([
  {
    name: 'no.1',
    children: [
      {
        name: 'no.1-1',
        children: [
          {
            name: 'no.1-1-1',
            children:[]
          }
        ]
      },
    ],
  }, {
    name:'no.2'
  }, {
    name: 'no.3',
    children: [{
      name:'no.3-1'
    }]
  }

])
</script>

<style scoped></style>

type.ts 属性数据的结构

export type TreeList = {
  name: string //名称
  icon?: string //图标可有可无
  children?: TreeList[] | [] //子节点 可有可无 还可能传空数组
}

第二种方式,export 一个name出去

第二种方式 就是像vue2 一样 export一个name出去

但是setup 语法糖下没办法使用 export

我们只需要再定义一个script标签就可以了

<template>
  <div class="tree">
    <div v-for="(item, index) in data" :key="item.name">
      每一层 {{ item.name }}
      <Tree v-if="item?.children?.length" :data='item.children' />
    </div>
  </div>
</template>

<script setup lang="ts">
import { TreeList } from '../ts/type'
type Props = {
  data?: TreeList[]
}
defineProps<Props>();
</script>
<!-- 
  第二种方式 就是像vue2 一样 export一个name出去
  但是setup 语法糖下没办法使用 export 
  我们只需要再定义一个script标签就可以了
 -->
<script lang="ts">
export default {
  name:'Tree'
}
</script>

<style scoped>
.tree {
  margin-left: 20px;
  border-left: 2px #01847f dashed;
}
</style>

效果图

我们还可以给树形递归的组件添加参数传递事件

要注意在树形组件的里层也得添加自定义事件

并且这个自定义事件传的函数很有讲究

Tree.vue

<template>
  <div class="tree">
    <div @click.stop="clickTreeItem(item)" v-for="(item, index) in data" :key="item.name">
      每一层 {{ item.name }}
      <Tree  @get-tree-item="clickTreeItem" v-if="item?.children?.length" :data='item.children' />
        <!-- Tree 组件不添加这个自定义事件的话  那么就只有最外层的根节点会向外传递数据 -->
      <!-- 注意此处派发的函数clickTreeItem没有传item参数了如果传了就相当于给树形组件(递归组件)的上级派发信息 没办法从外部拿到子节点所传递的数据了 -->
           <!--   @get-tree-item="clickTreeItem(item)"  写成这种形式的话  递归组件会依次向上层传递事件   -->
      <!-- 不传item的执行结果如下 -->
      <!--子组件派发的item Proxy {name: 'no.1-1-1', children: Array(0)}
          子组件派发的item Proxy {name: 'no.1-1-1', children: Array(0)}
          子组件派发的item Proxy {name: 'no.1-1-1', children: Array(0)}
          父组件得到的item Proxy {name: 'no.1-1-1', children: Array(0)} -->
      <!-- 传item的执行的结果如下 -->
      <!-- 子组件派发的item Proxy {name: 'no.1-1-1', children: Array(0)}
           子组件派发的item Proxy {name: 'no.1-1', children: Array(1)}
           子组件派发的item Proxy {name: 'no.1', children: Array(1)}
           父组件得到的item Proxy {name: 'no.1', children: Array(1)} -->
    </div>
  </div>
</template>

<script setup lang="ts">
import { TreeList } from '../ts/type'
type Props = {
  data?: TreeList[]
}
defineProps<Props>();

const emit =   defineEmits(['getTreeItem'])
const clickTreeItem=(item:TreeList)=>{
  console.log('子组件派发的item', item)
  emit('getTreeItem',item)
}
</script>
<!-- 
  第二种方式 就是像vue2 一样 export一个name出去
  但是setup 语法糖下没办法使用 export 
  我们只需要再定义一个script标签就可以了
 -->
<script lang="ts">
export default {
  name:'Tree'
}
</script>

<style scoped>
.tree {
  margin-left: 20px;
  border-left: 2px #01847f dashed;
}
</style>

App.vue

<template>
  <div>
    <Tree :data='data' @get-tree-item="getTreeItem"/>
  </div>
</template>

<script setup lang="ts">
import Tree from './components/Tree.vue'
import { reactive } from 'vue'
import {TreeList } from './ts/type'
const data = reactive<TreeList[]>([
  {
    name: 'no.1',
    children: [
      {
        name: 'no.1-1',
        children: [
          {
            name: 'no.1-1-1',
            children:[]
          }
        ]
      },
    ],
  }, {
    name:'no.2'
  }, {
    name: 'no.3',
    children: [{
      name:'no.3-1'
    }]
  }

])

const getTreeItem = (item:TreeList) => {
  console.log('父组件得到的item',item)
}
</script>

<style scoped></style>


http://www.kler.cn/news/163080.html

相关文章:

  • 【数据仓库-10】-- 数据仓库、数据湖和湖仓一体对比
  • 剑指 Offer(第2版)面试题 21:调整数组顺序使奇数位于偶数前面
  • 做数据分析为何要学统计学(4)——什么问题适合使用卡方检验?
  • 考研真题数据结构
  • python3安装redis
  • Navicat 技术指引 | 适用于 GaussDB 分布式的模型功能
  • Django的logging-日志模块的简单使用方法
  • 微信小程序网络请求二次封装
  • Java项目开发,业务比较复杂如何减少bug
  • 基于深度学习yolov5实现安全帽人体识别工地安全识别系统-反光衣识别系统
  • ArkTS快速入门
  • CentOS常用基础命令大全(linux命令)2
  • Pycharm Jupyter ModuleNotFoundError 问题解决
  • 【前端】CSS基础(学习笔记)
  • Python合并一个 Excel 里面的多张表
  • 虚幻学习笔记10—C++函数与蓝图的通信
  • django与数据库交互关于当前时间的坑
  • 2023.12.7 关于 MySQL 事务详解
  • C#云LIS系统源码 B/S架构,SaaS模式,可扩展性强
  • 数据结构——二叉树的链式结构
  • pcl-3 pcl结合opencv做svm分类(法向量特征数据)
  • 如何运用gpt改写出高质量的文章 (1)
  • 【计算机网络】应用层电子邮件协议
  • AWS Remote Control ( Wi-Fi ) on i.MX RT1060 EVK - 3 “编译 NXP i.MX RT1060”( 完 )
  • 奇点云2023数智科技大会来了,“双12”直播见!
  • 【游戏引擎 - C#脚本系统】6、C#端调用C++函数
  • 使用 Axios 进行网络请求的全面指南
  • echart中定义brush,默认状态,触发状态
  • MQTT协议对比TCP网络性能测试模拟弱网测试
  • Mybatis XML改查操作(结合上文)