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、效果

 

posted @ 2023-02-16 19:55  程序员冒冒  阅读(515)  评论(0编辑  收藏  举报