vue学习之-----组件递归调用
1、关键点
2、父组件
<template> <div> <div class="btn-title"> <el-button @click="addRule(ruleDataList.id)">添加父节点</el-button> </div> <RuleTable :pid="ruleDataList.id" :ruleData="ruleDataList.children" @delRule="delRule" @addRule="addRule"></RuleTable> </div> </template> <script> import RuleTable from './RuleTable.vue' export default { components: { RuleTable }, data() { return { ruleDataList: { id: this.$nanoid(),//自定义id lvl: 1,//节点等级 theme: '',//主题 time: '',//次数 children: [] } } }, methods: { addRule(id) { if (id === this.ruleDataList.id) {//>>>一级节点 this.ruleDataList.children.push({ id: this.$nanoid(),//自定义id lvl: 1,//节点等级 theme: '',//主题 time: '',//次数 children: [] }) } else { this.ruleDataList.children.map(e => { if (e.id === id) {//>>>二级节点 let obj = JSON.parse(JSON.stringify(e)) obj.id = this.$nanoid();//自定义id obj.lvl = 2 e.children.push(obj, { id: this.$nanoid(),//自定义id lvl: 2,//节点等级 theme: '',//主题 time: '',//次数 children: [] }) } else { let flag = e.children.find(i => i.id === id) if (flag) {//>>>三级节点 e.children.push({ id: this.$nanoid(),//自定义id lvl: 2,//节点等级 theme: '',//主题 time: '',//次数 children: [] }) } } }) } }, delRule(id) { this.ruleDataList.children = this.ruleDataList.children.filter(i => { // 如果是二级节点 if (i.children && i.children.length > 0) { i.children = i.children.filter(j => { return j.id != id }) return i } // 如果是一级节点 return i.id != id }).map(k => { if (k.children && k.children.length === 1) { let obj = JSON.parse(JSON.stringify(k.children[0])) obj.lvl = 1 return obj //如果只有一个二级节点,则变为一级节点 } return k //其余,则原样返回 }) } } } </script> <style> .btn-title { display: flex; justify-content: end; margin-bottom: 10px; } </style>
3、子组件RuleTable(递归调用)
<template> <el-card style="margin-top:5px"> <el-row> <el-col :span="2" align="center" v-if="ruleData.length > 1"> <div class="left-top" :style="'height:' + halfHeight + 'px'"></div> <div class="left-center">组</div> <div class="left-bottom" :style="'height:' + halfHeight + 'px'"></div> </el-col> <el-col :span="22" :id="pid"> <el-row v-for="item in ruleData" :key="item.id"> <RuleTable v-if="item.children.length > 0" :pid="item.id" :ruleData="item.children" @delRule="delRule" @addRule="addRule"></RuleTable> <el-form v-else> <el-col :span="8" class="pd5"> <el-form-item prop="theme"> <el-input v-model="item.theme" placeholder="请输入主题"></el-input> </el-form-item> </el-col> <el-col :span="8" class="pd5"> <el-form-item prop="time"> <el-input v-model="item.time" placeholder="请输入次数"></el-input> </el-form-item> </el-col> <el-col :span="6" class="pd5"> <el-button type="danger" @click="delRule(item.id)">删除</el-button> <el-button type="primary" @click="addRule(item.id)">新增</el-button> </el-col> </el-form> </el-row> </el-col> </el-row> </el-card> </template> <script> export default { name: 'RuleTable', //子组件的name名要和组件名一致 props: { ruleData: { type: Array, default: () => [] }, pid: { type: String, default: () => '' } }, data() { return { halfHeight: 0,//竖线的高度 } }, watch: { ruleData: { handler(val) { console.log("ruleData--val:", val) if (val) { this.updateHeight() } }, deep: true, immediate: true } }, methods: { delRule(id) { this.$emit('delRule', id) }, addRule(id) { this.$emit('addRule', id) }, updateHeight() { this.$nextTick(() => { let leftHeight = document.getElementById(this.pid + '').offsetHeight console.log("实时高度--leftHeight:", leftHeight) this.halfHeight = (leftHeight - 21) / 2 }) } } } </script> <style> .left-top { width: 2px; background-color: #bbb; } .left-bottom { width: 2px; background-color: #bbb; } .pd5 { padding-left: 5px; } </style>
4、效果