1、关键点

2、父组件

  1. <template>
  2. <div>
  3. <div class="btn-title">
  4. <el-button @click="addRule(ruleDataList.id)">添加父节点</el-button>
  5. </div>
  6. <RuleTable :pid="ruleDataList.id" :ruleData="ruleDataList.children" @delRule="delRule" @addRule="addRule"></RuleTable>
  7. </div>
  8. </template>
  9. <script>
  10. import RuleTable from './RuleTable.vue'
  11. export default {
  12. components: {
  13. RuleTable
  14. },
  15. data() {
  16. return {
  17. ruleDataList: {
  18. id: this.$nanoid(),//自定义id
  19. lvl: 1,//节点等级
  20. theme: '',//主题
  21. time: '',//次数
  22. children: []
  23. }
  24. }
  25. },
  26. methods: {
  27. addRule(id) {
  28. if (id === this.ruleDataList.id) {//>>>一级节点
  29. this.ruleDataList.children.push({
  30. id: this.$nanoid(),//自定义id
  31. lvl: 1,//节点等级
  32. theme: '',//主题
  33. time: '',//次数
  34. children: []
  35. })
  36. } else {
  37. this.ruleDataList.children.map(e => {
  38. if (e.id === id) {//>>>二级节点
  39. let obj = JSON.parse(JSON.stringify(e))
  40. obj.id = this.$nanoid();//自定义id
  41. obj.lvl = 2
  42. e.children.push(obj, {
  43. id: this.$nanoid(),//自定义id
  44. lvl: 2,//节点等级
  45. theme: '',//主题
  46. time: '',//次数
  47. children: []
  48. })
  49. } else {
  50. let flag = e.children.find(i => i.id === id)
  51. if (flag) {//>>>三级节点
  52. e.children.push({
  53. id: this.$nanoid(),//自定义id
  54. lvl: 2,//节点等级
  55. theme: '',//主题
  56. time: '',//次数
  57. children: []
  58. })
  59. }
  60. }
  61. })
  62. }
  63. },
  64. delRule(id) {
  65. this.ruleDataList.children = this.ruleDataList.children.filter(i => {
  66. // 如果是二级节点
  67. if (i.children && i.children.length > 0) {
  68. i.children = i.children.filter(j => {
  69. return j.id != id
  70. })
  71. return i
  72. }
  73. // 如果是一级节点
  74. return i.id != id
  75. }).map(k => {
  76. if (k.children && k.children.length === 1) {
  77. let obj = JSON.parse(JSON.stringify(k.children[0]))
  78. obj.lvl = 1
  79. return obj //如果只有一个二级节点,则变为一级节点
  80. }
  81. return k //其余,则原样返回
  82. })
  83. }
  84. }
  85. }
  86. </script>
  87. <style>
  88. .btn-title {
  89. display: flex;
  90. justify-content: end;
  91. margin-bottom: 10px;
  92. }
  93. </style>

3、子组件RuleTable(递归调用)

  1. <template>
  2. <el-card style="margin-top:5px">
  3. <el-row>
  4. <el-col :span="2" align="center" v-if="ruleData.length > 1">
  5. <div class="left-top" :style="'height:' + halfHeight + 'px'"></div>
  6. <div class="left-center"></div>
  7. <div class="left-bottom" :style="'height:' + halfHeight + 'px'"></div>
  8. </el-col>
  9. <el-col :span="22" :id="pid">
  10. <el-row v-for="item in ruleData" :key="item.id">
  11. <RuleTable v-if="item.children.length > 0" :pid="item.id" :ruleData="item.children"
  12. @delRule="delRule" @addRule="addRule"></RuleTable>
  13. <el-form v-else>
  14. <el-col :span="8" class="pd5">
  15. <el-form-item prop="theme">
  16. <el-input v-model="item.theme" placeholder="请输入主题"></el-input>
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="8" class="pd5">
  20. <el-form-item prop="time">
  21. <el-input v-model="item.time" placeholder="请输入次数"></el-input>
  22. </el-form-item>
  23. </el-col>
  24. <el-col :span="6" class="pd5">
  25. <el-button type="danger" @click="delRule(item.id)">删除</el-button>
  26. <el-button type="primary" @click="addRule(item.id)">新增</el-button>
  27. </el-col>
  28. </el-form>
  29. </el-row>
  30. </el-col>
  31. </el-row>
  32. </el-card>
  33. </template>
  34. <script>
  35. export default {
  36. name: 'RuleTable', //子组件的name名要和组件名一致
  37. props: {
  38. ruleData: {
  39. type: Array,
  40. default: () => []
  41. },
  42. pid: {
  43. type: String,
  44. default: () => ''
  45. }
  46. },
  47. data() {
  48. return {
  49. halfHeight: 0,//竖线的高度
  50. }
  51. },
  52. watch: {
  53. ruleData: {
  54. handler(val) {
  55. console.log("ruleData--val:", val)
  56. if (val) {
  57. this.updateHeight()
  58. }
  59. },
  60. deep: true,
  61. immediate: true
  62. }
  63. },
  64.  
  65. methods: {
  66. delRule(id) {
  67. this.$emit('delRule', id)
  68. },
  69. addRule(id) {
  70. this.$emit('addRule', id)
  71. },
  72. updateHeight() {
  73. this.$nextTick(() => {
  74. let leftHeight = document.getElementById(this.pid + '').offsetHeight
  75. console.log("实时高度--leftHeight:", leftHeight)
  76. this.halfHeight = (leftHeight - 21) / 2
  77. })
  78. }
  79. }
  80. }
  81. </script>
  82. <style>
  83. .left-top {
  84. width: 2px;
  85. background-color: #bbb;
  86. }
  87.  
  88. .left-bottom {
  89. width: 2px;
  90. background-color: #bbb;
  91. }
  92.  
  93. .pd5 {
  94. padding-left: 5px;
  95. }
  96. </style>

4、效果

vue学习之-----组件递归调用的更多相关文章

  1. vue学习之组件

    组件从注册方式分为全局组件和局部组件. 从功能类型又可以分为偏视图表现的(presentational)和偏逻辑的(动态生成dom),推荐在前者中使用模板,在后者中使用 JSX 或渲染函数动态生成组件 ...

  2. 【vue】父组件主动调用子组件 /// 非父子组件传值

    一  父组件主动调用子组件: 注意:在父组件使用子组件的标签上注入ref属性,例如: <div id="home"> <v-header ref="he ...

  3. 浅谈vue学习之组件通信

    vue用组件化简化了我们编写代码的复杂度,组件之间经常会出现数据传递的情况,那么组件之间是怎样通信的呢? 使用props传递数据 组件实例的作用域是孤立的.这意味着不能 (也不应该) 在子组件的模板内 ...

  4. vue学习之四组件系统

    vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. 一.Vue.js组件系统 每一个 ...

  5. vue:子组件通过调用父组件的方法的方式传参

    在本案例中,由于子组件通过调用父组件的方法的方式传参,从而实现修改父组件data中的对象,所以需要啊使用$forceUpdate()进行强制刷新 父组件: provide() { return { s ...

  6. Vue学习之--------组件的基本使用(非单文件组件)(代码实现)(2022/7/22)

    文章目录 1.为啥要使用组件 2.基本使用 3.代码实例 4.测试效果 5.注意点 1.为啥要使用组件 好用啊.像堆积木一样 2.基本使用 Vue中使用组件的三大步骤: 一.定义组件(创建组件) 二. ...

  7. Vue学习之组件切换及父子组件小结(八)

    一.组件切换: 1.v-if与v-else方式: <!DOCTYPE html> <html lang="en"> <head> <met ...

  8. Vue学习之--------组件嵌套以及VueComponent的讲解(代码实现)(2022/7/23)

    欢迎加入刚建立的社区:http://t.csdn.cn/Q52km 加入社区的好处: 1.专栏更加明确.便于学习 2.覆盖的知识点更多.便于发散学习 3.大家共同学习进步 3.不定时的发现金红包(不多 ...

  9. Vue学习笔记-组件通信-子传父(自定义事件)

    props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中.我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成.什么时候需要自定义事件呢?当子组件需要向父组件传递 ...

  10. vue 学习一 组件生命周期

    先上一张vue组件生命周期的流程图 以上就是一个组件完整的生命周期,而在组件处于每个阶段时又会提供一些周期钩子函数以便我们进行一些逻辑操作,而总体来讲 vue的组件共有8个生命周期钩子 beforeC ...

随机推荐

  1. vivo官网App模块化开发方案-ModularDevTool

    作者:vivo 互联网客户端团队- Wang Zhenyu 本文主要讲述了Android客户端模块化开发的痛点及解决方案,详细讲解了方案的实现思路和具体实现方法. 说明:本工具基于vivo互联网客户端 ...

  2. 用Redis实现延迟队列,我研究了两种方案,发现并不简单

    大家好,我是三友~~ 背景 前段时间有个小项目需要使用延迟任务,谈到延迟任务,我脑子第一时间一闪而过的就是使用消息队列来做,比如RabbitMQ的死信队列又或者RocketMQ的延迟队列,但是奈何这是 ...

  3. ubuntu20.04安装systemback

    sudo add-apt-repository --remove ppa:nemh/systemback sudo apt-key adv --keyserver keyserver.ubuntu.c ...

  4. windows C++

    #include <Windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar ...

  5. shrio

    Shrio 页面报错 <link rel="shortcut icon" href="#"/> 简单的安全框架 官网:https://shiro.a ...

  6. linux下删除文件夹的软链接时注意千万不能在后面加反斜杠,千万不要用强制删除,否则下面2种场景,你会把源文件删除,要闯祸的

    今天遇到一个坑,自己在子目录下创建了父目录的软链接,导致可以无限循环进入父目录 [clouder@ana53 dir1]$ ll total 8 -rw-rw-r-- 1 clouder cloude ...

  7. 【KAWAKO】TVM-在ubuntu服务器上的安装

    目录 下载源码 安装依赖库 修改config.cmake文件 编译 安装python库 添加tophub 简单验证 官方的安装教程在这里 下载源码 从Download Page中下载下来的源码是0.8 ...

  8. Nacos服务调用(基于Openfeign)

    在<<Nacos服务注册>>这篇文章里,我搭建了一个nacos服务中心,并且注册了一个服务,下面我们来看在上一篇文章的基础上,怎样用Openfeign来调用这个服务. 0.同上 ...

  9. addeventlistener可以这样表示

    事件绑定方法1: //找到id为category的div,绑定onmouseover事件 $("#category")[0].addEventListener("mous ...

  10. 结合ChatGPT体验新必应new bing 的惊喜:这是我第一次使用的感受

    前言 最近相信大家都被 ChatGPT 刷屏了,它的爆火大家是有目共睹的,微软的新必应(New Bing) 是结合了比 ChatGPT 更强大的新一代 OpenAI 语言模式,接下来我们一起来&quo ...