主要涉及組件自調(diào)用實(shí)現(xiàn)渲染遏弱,js實(shí)現(xiàn)遞歸數(shù)組的增刪
老規(guī)矩艇炎,還是先看效果
- 這塊主要分了幾個組件來實(shí)現(xiàn):連接線、卡片腾窝、連接線+卡片(含自身嵌套缀踪,這個組件就是調(diào)用了前面連接線和卡片的組件居砖,大家可以合在一起)、父組件調(diào)用驴娃,以及通過eventBus實(shí)現(xiàn)增加奏候、刪除操作
連接線這塊比較簡單,不需要的跳過
<!-- ConnectLine.vue 連接關(guān)系線 !-->
<template>
<div class="line-wrap">
<div class="line line-top"></div>
<!-- 需要的可以在這里做一些關(guān)系選擇唇敞,涉及業(yè)務(wù)蔗草,隱去了 -->
<div class="line line-bottom"></div>
</div>
</template>
<script>
export default {
name: "ConnectLine",
data() {
return {};
},
};
</script>
<style lang='scss' scoped>
.line-wrap {
display: flex;
flex-direction: column;
align-items: center;
.line {
flex: 1;
width: 30px;
border-left: 1px solid #c0c4cc;
&.line-bottom {
margin-bottom: 20px;
}
}
}
</style>
下面看一下卡片這部分,涉及業(yè)務(wù)內(nèi)容疆柔,我用id代替了卡片內(nèi)容(此處id也作為唯一key值在組件間傳遞)
<!-- RuleCard.vue 卡片組件 !-->
<template>
<div class="card-wrap">
<el-card>{{item.id}}</el-card>
<div class="operate-wrap">
<i class="icon el-icon-delete" @click="editCard('delete')"></i>
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link"><i class="icon el-icon-plus"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="addEqual">同級</el-dropdown-item>
<el-dropdown-item command="addChild">子級</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
export default {
name: "RuleCard",
props: {
item: Object,
},
data() {
return {};
},
methods: {
//刪除卡片
editCard() {
this.$emit("editCard", "delete", this.item.id);
},
//增加卡片
handleCommand(command) {
this.$emit("editCard", command, this.item.id);
},
},
};
</script>
<style lang='scss' scoped>
.card-wrap {
width: 370px;
display: flex;
align-items: center;
.el-card {
flex: 1;
margin-bottom: 10px;
/deep/.el-card__body {
padding: 10px;
}
}
.operate-wrap {
width: 70px;
.icon {
font-size: 16px;
padding: 5px;
margin-left: 5px;
cursor: pointer;
}
}
}
</style>
下面就是連接線+卡片組件咒精,前面準(zhǔn)備工作都做好了,這個組件就比較簡單(嵌套自身通過本身組件的name實(shí)現(xiàn))
<!-- RulePanel.vue 面板組件 !-->
<template>
<div class="rule-wrap">
<!-- 設(shè)置連接線:數(shù)組長度大于1旷档,或含有子級 -->
<connect-line v-if="list.length>1||(list[0]&&list[0].children&&list[0].children.length>0)"></connect-line>
<div>
<div v-for="(li,i) in list" :key="i">
<!-- 卡片 -->
<rule-card :item="li" @editCard="editCard"></rule-card>
<!-- 嵌套自身 -->
<RulePanel :list="li.children"></RulePanel>
</div>
</div>
</div>
</template>
<script>
import ConnectLine from "./ConnectLine";
import RuleCard from "./RuleCard";
import Bus from "@/plugins/eventBus";
export default {
name: "RulePanel",
components: { ConnectLine, RuleCard },
props: {
list: {
type: Array,
default: () => [],
},
},
data() {
return {};
},
methods: {
//觸發(fā)卡片刪除模叙、添加
editCard(type, id) {
Bus.$emit("editCard", type, id);
},
},
};
</script>
<style lang='scss' scoped>
.rule-wrap {
display: flex;
overflow-x: auto;
}
</style>
最后就是父組件調(diào)用啦
<!-- ElementRule.vue 父組件 !-->
<template>
<div class="custom-panel-tab__content">
<rule-panel :list="list"></rule-panel>
</div>
</template>
<script>
import RulePanel from "./components/RulePanel";
import Bus from "@/plugins/eventBus";
export default {
name: "ElementRule",
components: { RulePanel },
data() {
return {
radio: "1",
list: [
{ id: "1", children: [] },
{
id: "2",
children: [
{
id: "2-1",
children: [{id: "2-1-1", children: [{ id: "2-1-1-1" }, { id: "2-1-1-2" }]}, { id: "2-1-2" }],
},
],
},
],
};
},
created() {
//監(jiān)聽卡片刪除、添加
Bus.$on("editCard", (type, id) => {
if (type === "delete") {
this.deleteCard(this.list, id);
} else {
this.addCard(this.list, type, id);
}
});
},
methods: {
//刪除卡片
deleteCard(arr, id) {
if (this.list.length === 1 && this.list[0].id === id) {
this.$message("至少保留一個卡片");
return;
}
arr.forEach((item, index) => {
if (item.id === id) {
arr.splice(index, 1);
return;
}
if (item.children && item.children.length > 0) {
return this.deleteCard(item.children, id);
}
});
},
//增加卡片
addCard(arr, type, id) {
arr.forEach((item) => {
if (item.id === id) {
//同級
if (type === "addEqual") {
let indArr = id.split("-");
let num = arr.length + 1;
indArr[indArr.length - 1] = num;
arr.push({ id: indArr.join("-") });
}
//子級
if (type === "addChild") {
let newId = `${id}-${
item.children ? item.children.length + 1 : "1"
}`;
item.children
? item.children.push({ id: newId })
: (item.children = [{ id: newId }]);
}
this.list = JSON.parse(JSON.stringify(this.list)); //強(qiáng)制頁面刷新
return;
}
if (item.children && item.children.length > 0) {
return this.addCard(item.children, type, id);
}
});
},
},
};
</script>
<style scoped lang="scss">
.node-type {
margin-bottom: 20px;
}
</style>
這樣就好啦~~~
- PS: 附一下eventBus的代碼吧
import Vue from 'vue'
export default new Vue()