根据业务需要,实现树结构的节点新增编辑删除功能,主要逻辑是利用树节点的scopedSlots属性对其进行自定义改造,监听悬停事件在节点右侧出现增删改对应图标,点击图标出现弹窗表单对内容进行修改,具体代码如下:
// 模板部分
<template>
<a-tree
v-if="factorTreeData.length > 0"
show-icon
default-expand-parent
:tree-data="factorTreeData"
:defaultExpandAll="true"
:autoExpandParent="true"
:default-selected-keys="selectedKeys"
@select="onTreeSelect">
<template slot="custom" slot-scope="item">
<div @mouseenter="onMouseEnter(item)" style="position: relative;">
<span class="treeMode">
<a-icon v-if="!item.isLeaf" :type="item.expanded ? 'folder-open' : 'folder'" />
<a-icon type="file" v-if="item.isLeaf"/>
<span style="margin-left: 5px">
{{ item.title }}
</span>
</span>
<a-space
@click.stop
v-if="mouseItemId === item.key"
style="position: absolute; right: 5px; top: 0"
>
<a-button type="primary" size="small" icon="plus" @click="addTreeNode(item)" />
<a-button type="primary" size="small" icon="edit" @click="editTreeNode(item)" />
<a-button type="primary" size="small" icon="delete" @click="delTreeNode(item)" />
</a-space>
</div>
</template>
</a-tree>
<a-modal
v-drag-modal
v-model="visible"
:title="modalTitle"
:destroyOnClose="true"
@ok="handleSave"
:width="800"
:bodyStyle="{'height': '480px', 'overflow-y': 'auto'}"
centered
>
<ItemModal ref="childModal" :formObj="formObj"/>
</a-modal>
</template>
//js部分
<script>
export default {
components: {
ItemModal: () => import ('./item-modal') // 表单弹窗
},
data () {
return {
// 树结构
factorTreeData: [],
expandedKeys: [],
selectedKeys: [],
mouseItemId: '',
// 弹窗
modalTitle: '',
visible: false,
formObj: {}
}
},
mounted () {
this.getTreeData()
},
methods: {
// 获取树(模拟数据)
getTreeData () {
this.factorTreeData= [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
],
}
]
this.dealTreeData(this.factorTreeData || [])
this.selectedKeys = [this.factorTreeData.children[0].key]
this.mouseItemId = this.factorTreeData.children[0].key
},
// 给每个节点添加自定义属性
dealTreeData (dataArr) {
dataArr.forEach((el, i) => {
el.value = el.key
if (el.children && el.children.length > 0) {
el.isLeaf = false
el.selectable = false
el['scopedSlots'] = { title: 'custom' }
this.dealTreeData(el.children)
} else {
el.isLeaf = true
el['scopedSlots'] = { title: 'custom' }
}
})
},
// 节点选择事件
onTreeSelect (selectedKeys) {
},
// 树鼠标悬停事件
onMouseEnter (item) {
this.mouseItemId = item.key
},
// 添加树节点
addTreeNode (item) {
this.formObj = {
id: null,
pid: item.parentId,
name: '',
displayOrder: '',
status: '',
remark: ''
}
this.modalTitle = '新增'
this.visible = true
},
// 编辑树节点
editTreeNode (item) {
getTreeInfo({ id: item.id }).then(res => {
if (res.code === 200) {
this.formObj = {
id: res.result[0].id,
pid: res.result[0].pid,
name: res.result[0].name,
displayOrder: res.result[0].displayOrder,
status: res.result[0].status,
remark: res.result[0].remark
}
this.modalTitle = '编辑'
this.visible = true
}
}).catch(err => console.log(err))
},
// 保存树节点
handleSave() {},
// 删除树节点
delTreeNode (item) {
const that = this
this.$confirm({
title: '确定要删除吗?',
onOk () {
delTree({ ids: item.id }).then(res => {
if (res.code === 200) {
that.$message.success('删除成功!')
that.getTree() // 重新请求树数据
} else {
that.$message.error('删除失败!')
}
}).catch(err => {
console.log(err)
this.$message.error('删除失败!')
})
}
})
}
}
</script>
<style lang="less" scoped>
// 树
::v-deep .ant-tree {
li {
padding: 1px 0;
}
.ant-tree-node-content-wrapper {
width: calc(100% - 24px);
height: 32px;
line-height: 32px;
}
.treeMode {
height: 30px;
width: 70%;
display: flex;
align-items: center;
span {
height: 30px;
display: inline-block;
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 5px;
}
}
}
::v-deep .ant-tree.ant-tree-directory > li span.ant-tree-node-content-wrapper::before {
height: 32px;
}
</style>
示例: