树形结构的节点自定义: 序号+输入框+增删按钮
功能实现:
- 单个节点的增加删除
- 多个节点批量的增加删除
- 保存生成新的树形数据
- ...
参考代码:
<template>
<div>
<!-- 按钮 -->
<el-button type="primary" plain round @click="handlerCreate"
>新建</el-button
>
<el-button type="primary" plain round @click="handlerDelete"
>删除</el-button
>
<el-button type="primary" plain round @click="save">保存</el-button>
<!-- 树形控件 -->
<el-card>
<el-tree
ref="tree"
class="tree"
:data="treeData"
node-key="id"
:props="{ label: 'label', children: 'children' }"
show-checkbox
:expand-on-click-node="false"
@check="selectRows"
:default-expand-all="true"
>
<template v-slot="{ node, data }">
<div>
<!-- 每条数据的序号 -->
<span class="index">{{
`${
getPosByIdInTree(treeData, data.id).length === 1
? ++getPosByIdInTree(treeData, data.id)[0]
: ++getPosByIdInTree(treeData, data.id)[0] +
'.' +
++getPosByIdInTree(treeData, data.id)[1]
}`
}}</span>
<!-- 输入框 -->
<el-input
style="width: 500px"
v-model="data.label"
placeholder="请输入内容"
clearable
></el-input>
<!-- 单个删除 -->
<el-button
style="margin-left: 10px"
type="success"
plain
circle
icon="el-icon-minus"
@click="handlerMinus(node, data)"
></el-button>
<!-- 单个新增,二级节点隐藏新增按钮 -->
<el-button
v-if="data.parentId === null"
type="success"
plain
circle
icon="el-icon-plus"
@click="handlerAdd(node, data)"
></el-button>
</div>
</template>
</el-tree>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
id: 1,
treeData: [
{ label: '烛光照亮了晚餐', children: [], id: 1, parentId: null },
],
selectionRows: [],
halfCheckedNodes: [],
}
},
methods: {
// 保存
save() {
console.log(this.treeData) // 获取创建的树状结构
const source = 3
const pos = this.getPosByIdInTree(this.treeData, source)
console.log(pos) // 不算根节点,测试通过
},
// 单个新增子节点
handlerAdd(node, data) {
console.log(node)
const newChild = {
id: ++this.id,
label: '爱情转移',
children: [],
parentId: data.id,
}
if (!data.children) {
this.$set(data, 'children', [])
}
data.children.push(newChild)
},
// 删除子节点节点
handlerMinus(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
},
// 新增一级节点
handlerCreate() {
this.treeData.push({
label: '却照不出个答案',
children: [],
id: ++this.id,
parentId: null,
})
},
// 保存选择状态
selectRows(data, arr) {
console.log(data, arr)
this.selectionRows = arr.checkedNodes
console.log(arr.halfCheckedKeys)
this.halfCheckedNodes = arr.halfCheckedNodes
},
// 批量删除节点
handlerDelete() {
if (this.selectionRows === []) return
this.selectionRows.forEach((item) => {
this.handlerMinus(this.$refs.tree.getNode(item), item)
})
this.halfCheckedNodes.forEach((item) => {
this.$refs.tree.setChecked(item, false, true)
})
},
// 获取每个节点的索引
getPosByIdInTree(tree, id) {
const tmp = [] // 路径数组
const FindPos = (sourceTree, sourceId) => {
sourceTree.forEach((item, index) => {
if (item.id === sourceId) {
tmp.push(index)
} else {
item.children.forEach((t, i) => {
if (t.id === sourceId) {
tmp.push(i)
tmp.push(index)
}
})
}
})
}
FindPos(tree, id)
return tmp.reverse()
},
},
}
</script>
<style lang="less" scope>
.el-tree-node__content {
height: 50px !important;
}
.index {
display: inline-block;
background-color: #ddd;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
border-radius: 5px;
}
</style>