NoteZ_技术博客 NoteZ_技术博客
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)

NoteZ_技术博客

前端界的小学生
🏠 首页
  • 📚 Web技术
  • 📋 Npm笔记
  • 📑 Markdown
  • 📄 Git笔记
  • 📝 Nginx文档
  • 📓 Linux文档
  • 📖 技术文档
  • 📜 其他文档
  • 🧊 NodeJs
  • 🎡 Express
  • 🔥 Rust
  • 🎉 Koa2
  • 🍃 MongoDB
  • 🐬 MySql
  • 🥦 Oracle
  • 🍁 Python
  • 🍄 JavaScript
  • 🌰 CSS
  • 🧄 HTML
  • 🥑 Canvas
  • 🌽 Nuxt
  • 🍆 React
  • 🥜 Vue
  • 🧅 TypeScript
  • 🌶️ AI
  • 📘 分类
  • 📗 标签
  • 📙 归档
⚜️ 在线编辑 (opens new window)
  • 📁 站点收藏
  • 📦 前端组件库
  • 📊 数据可视化
  • 🌈 开源插件
  • 🎗️ 关于我
  • 🔗 友情链接
GitHub (opens new window)
  • JavaScript笔记

  • CSS笔记

  • HTML笔记

  • Canvas笔记

  • Nuxt笔记

  • React笔记

  • Vue笔记

    • markdown(md-editor-v3)简单使用
    • Prop 验证 与 非 Prop 的 Attribute
    • transition-group列表过渡
    • transition过渡&动画
    • vetur 中 eslint 的问题
    • vite 打包时内存溢出处理方案
    • Vite2 + Vue3添加svg的使用并通过svg实现自定义Icon组件
    • Vite项目构建优化之移除console.log和其他生产日志
    • vsCode 之 Monaco Editor 在 vue-cli3.0 中的使用方法
    • vue cli3 中的使用Luckysheet和Luckyexcel
    • vue 与 Koa 上传示例代码
    • vue 中 axios 如何取消请求,取消前面一个或多个请求
    • Vue 中 node-sass 安装失败简单解决方案
    • vue 中使用 pinia 状态管理教程
    • vue 中使用 web worker
    • vue 中封装 Axios 和 管理 API 接口
    • vue 中的 hash 与 history 两种路由模式
    • Vue 中的鼠标事件汇总
    • Vue 实现 Base64 图片上传
    • vue 强制刷新组件
    • Vue 组件中 v-mode 的本质以及实现方式
    • vue 组件中的.native 原生事件(@click.native)
    • Vue 组件中的.native原生事件(@click.native)
    • Vue 页面路由(router)权限控制和登陆验证
    • Vue 项目中如何在打包时清除 console 和 debugger
    • Vue 项目打包去除 .map 文件方法
    • Vue 预渲染之 prerender-spa-plugin 的配置使用
    • vue-cli 2.x和3.x配置移动端适配px自动转为rem
    • vue-cli3 如何实现pc端自适应
    • vue-cli3.0 开启 Gzip 压缩方法
    • Vue-cli3.0 监听路由变化的几种方式
    • Vue-cli3.0 结合 axios 解决生产环境中的跨域问题
    • vue-cli3.0移动端项目将px转换成rem
    • vue-cli3.x项目兼容ie解决方案
    • vue-router传递参数的几种方式
    • Vue2-ace-editor 基本使用方法
    • vue2.x 插槽slot使用总结
    • Vue2.x 组件通信方式
    • vue3 + vite 自适应(rem 适配)方法
    • vue3+vite:本地代理,配置proxy
    • Vue3.0 基础知识点总结
    • Vue3.0 挂载方法,添加全局属性
    • vue3.0之全局变量app.config.globalProperties的使用
    • vue3.2+elelmenui-plus+vite 按需导入ui组件库
    • vue3.x 中使用 ol (openlayer)地图
    • Vue3.x 组件通信方式
    • Vue3全局变量的定义和使用
    • Vuex使用记录
    • vue中使用html2canvas将html页面转为图片并且下载该图片
    • vue中父子组件之间的通信
    • Vue中的防抖函数封装和使用
    • Vue中配合clipboard.js实现点击按钮复制内容到剪切板
    • vue使用monaco editor时报错 Unexpected usage at EditorSimpleWorker.loadForeignModule
    • Vue列表渲染之数组、对象更新检测
    • Vue实现下拉滚动加载刷新功能
    • Vue开发中安装库经常报错
    • Vue技术框架
    • Vue生命周期
    • Vue监听store中数据变化的两种方式
    • Vue非父子组件之间通信的几种方式
    • Vue项目 解决 vuex 在页面刷新后数据丢失的问题
    • vue项目nginx部署子目录_vue 多项目部署_二级目录 copy
    • 使用 monaco-editor 汉化 右键菜单汉化
    • 使用 vite 脚手架创建 vue3 项目
    • 使用animate库
    • 使用vue实现鼠标框选文件的功能
    • 使用vue的transition标签结合css样式完成动画
    • 关于Vue项目优化方案总结
    • 关于解决vue-cli2.xx、vue-cli3.xx项目在ie中白屏的方案总结
    • 利用create-nuxt-app脚手架创建NuxtJS应用
    • 国际化插件 vue-i18n 使用方法
    • 在 vite-vue3.x 中的使用 vscode monaco-editor 方法
    • 在 Vue 中 如何使用 jsencrypt 实现 Rsa 进行加密
    • 在 vue 中使用 jsPlumb 总结
    • 在 vue 中使用 v-viewer 预览图方法
    • 在 Vue 中读取本地文本文件(兼容各种浏览器)
    • 在 vue 或 vuex 中如何使用 axios 进行请求操作
    • 在 vue 项目中 mock 的基本使用方法
    • 在 vue-cli3 项目更改 favicon 图标
    • 在 vue-cli3.0 中使用 Sass 全局变量
    • 在vue3+vite中使用markdown(v-md-editor)编辑器
    • 在vue中如何使用watch深度监听对象中值的变化
    • 基于 vue 列表拖拽排序
    • 基于 vue 图片裁剪(vue-cropper)
    • 基于 vue 的 CodeMirror 代码编辑器
    • 如何在 vue 中使用 swiper 插件创建轮播图
    • 如何在 vue 中实现代码高亮?
    • 如何在 Vue-cli3.0 中使用 prerender-spa-plugin 进行预渲染
    • 如何用 vue 实现一个虚拟列表
    • 清除项目中无用的console.log代码方法
    • 解决vue-cli3.0中提示syntax 'classProperties' isn't currently enabled的错误
    • 记录vite打包vue项目内存溢出问题及解决方法
    • Vite中使用 svg-sprite-loader加载svg文件
    • vite引入svg图片
    • vue 使用CompressionPlugin压缩解决打包后文件过大的问题
    • vue2.x递归组件 树形组件
    • vue3.x递归组件 树形组件
      • 方式一
      • 方式二
      • 递归传递事件
    • 使用Vite快速构建Vue3+ts+pinia脚手架
    • 启动vue项目时报错digital envelope routines__unsupported
    • Pinia 快速入门(使用教程)
    • 关于 Vite Vue 辨别当前所处于什么(生产、开发)环境
  • TypeScript笔记

  • AI相关笔记

  • 开发文档
  • Vue笔记
NoteZ
2024-02-20
目录

vue3.x递归组件 树形组件

# 方式一

直接自己调用自己

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

type.ts 属性数据的结构

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

# 方式二

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 递归传递事件

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

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

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#vue
上次更新: 2024/02/20, 17:31:36
vue2.x递归组件 树形组件
使用Vite快速构建Vue3+ts+pinia脚手架

← vue2.x递归组件 树形组件 使用Vite快速构建Vue3+ts+pinia脚手架→

最近更新
01
Gitea数据备份与还原
03-10
02
Linux 中使用 rsync 同步文件目录教程
03-10
03
Linux 使用 rsync 互相传输同步文件的简单步骤
03-08
更多文章>
Theme by Vdoing | Copyright © 2019-2025 NoteZ,All rights reserved | 冀ICP备2021027292号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式