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>
相关推荐
名字还没想好☜32 分钟前
Next.js App Router 数据获取:fetch 缓存、revalidate 与 dynamic 一次讲清
前端
成都渲染101云渲染66665 小时前
如何在3ds Max中实现更快、更高质量的渲染
前端·javascript·人工智能
闲猫7 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
paopaokaka_luck8 小时前
英语单词学习系统的设计与实现(基于艾宾浩斯遗忘曲线的智能复习机制、语音朗读、多题型测试与错题自动收录、Echarts图形化分析)
vue.js·spring boot·后端·echarts
自信的未来9 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
SRET9 小时前
Mineradio 沙盒隔离安装完全指南 | 一键安全运行 Electron 应用!!!
javascript·经验分享·安全·electron·aigc·音视频·ai编程
全栈前端老曹9 小时前
【MongoDB】安全与权限管理 —— 用户认证、角色权限、SSL 加密
前端·javascript·数据库·安全·mongodb·nosql·ssl
zhangxingchao10 小时前
AI大模型核心八:从 Agent Skill、长文档 RAG 到知识库更新与训练策略
前端·人工智能·后端
zhangxingchao10 小时前
AI大模型核心七:从 Workflow、RAG、记忆治理到幂等性
前端·人工智能·后端
gyx_这个杀手不太冷静11 小时前
Agent开发进阶指南(第 1 章):AI Agent 到底是什么?
前端·agent·ai编程