vue-antd tree组件自定义增删改功能
在VMS2.0 开发过程中,使用了vue-antd组件。然而,根据产品和交互的需求,需要实现以下设计稿的效果。使得用户可以直接在树节点上直接操作。
通过调研发现,vue-antd 自带的组件库只能实现以下样式展现,并不能直接在树节点上进行操作。
网上资料也搜寻了很多,无果,所以只能自己动手。最终实现效果如下图:
(顶级节点不能删除 为业务需求,可以忽略)
可以看到,新增、编辑和删除的具体实现效果。实现步骤如下:
一,数据格式
<a-tree :treeData="testData"></a-tree>
let treeData = [
{
id: 1,
key: 1,
isEdit: false, // 是否处于编辑状态
isNewItem: false, // 该节点是否是新增节点
title: "节点名字",
depth: 1, // 该节点的层级
scopedSlots: { title: "custom" }, // 自定义组件需要绑定
children: [
{
id: 2,
key: 2,
isEdit: false, // 是否处于编辑状态
isNewItem: false, // 该节点是否是新增节点
title: "子节点名字",
depth: 2, // 该节点的层级
scopedSlots: { title: "custom" }
}
]
}
];
目前效果:
设置树节点的icon
<a-tree :treeData="testData">
<span slot="switcherIcon" class="icon-plus"></span>
</tree>
<style lang="less" scoped>
/deep/ .ant-tree-switcher.ant-tree-switcher_open {
.icon-plus {
background-image: url("~@/assets/minus.png"); // 展开节点时的icon
}
}
/deep/ .ant-tree-switcher.ant-tree-switcher_close {
.icon-plus {
background-image: url("~@/assets/plus.png"); // 收起节点时的icon
}
}
</style>
二,增删改 按钮展示
<a-tree :treeData="testData">
<span slot="switcherIcon" class="icon-plus"></span>
<template slot="custom" slot-scope="item">
<span class="node-title">{{ item.title }} </span>
<span class="icon-wrap">
<icon name="delete" />
</span>
<span class="icon-wrap">
<icon name="edit" />
</span>
<span class="icon-wrap">
<icon name="plus" />
</span>
</template>
</a-tree>
效果果如下图(样式部分省略):
二,新增功能
template会渲染每个节点,我们新增元素时,应该展示一个输入框,待用户输入新节点名称。于是可以创建一个空间点,通过 isNewItem:true
来展示输入框。
<template slot="custom" slot-scope="item">
<!-- 如果是新节点 -->
<span v-if="item.isNewItem">
<input type="text" class="editInput" v-model="item.name" />
<span class="tree-cancle_icon edit-require_icon">
<a-icon type="close-circle" />
</span>
<span class="tree-save_icon edit-require_icon">
<a-icon type="check-circle" />
</span>
</span>
<span v-else>
<span class="node-title">{{ item.title }} </span>
<span class="icon-wrap">
<icon name="delete" />
</span>
<span class="icon-wrap" @click="editNode(item)">
<icon name="edit" />
</span>
<span class="icon-wrap" @click="addNewNode(item)">
<icon name="plus" />
</span>
</span>
</template>
<script>
点击添加事件( item ){ // item为点击添加按钮时的节点
let newItem = {
id: Math.ceil(Math.random() * 10000), // 避免和已有的id冲突
key: Math.ceil(Math.random() * 10000), // 避免和已有的key冲突
isEdit: false,
name: "",
isNewItem: true,
title: "",
depth: item.depth + 1, // 如果需要添加顶级节点,值为0
scopedSlots: { title: "custom" },
children: []
}
// index 是点击节点的位置
this.treeData[index].children.push(newNode);
</script>
效果如下(样式省略)
二,编辑功能
编辑的话,只需要在原节点上进行操作。所以我们在 v-else
进行操作。
<div v-else>
<!-- 编辑时展示输入框 -->
<div v-if="item.isEdit">
<input type="text" v-model="item.title" class="editInput" />
<span class="tree-cancle_icon edit-require_icon">
<a-icon type="close-circle" />
</span>
<span class="tree-save_icon edit-require_icon" >
<a-icon type="check-circle" />
</span>
</div>
<!-- 否则展示原来的节点信息 -->
<div v-else>
<span class="node-title">{{ item.title }} </span>
<span class="icon-wrap">
<icon name="delete" />
</span>
<span class="icon-wrap" >
<icon name="edit" />
</span>
<span class="icon-wrap" >
<icon name="plus" />
</span>
</div>
</div>
完整代码如下:
<a-tree :treeData="testData">
<span slot="switcherIcon" class="icon-plus"></span>
<template slot="custom" slot-scope="item">
<!-- 如果是新节点 -->
<span v-if="item.isNewItem">
<input type="text" class="editInput" v-model="item.name" />
<span class="tree-cancle_icon edit-require_icon">
<a-icon type="close-circle" />
</span>
<span class="tree-save_icon edit-require_icon">
<a-icon type="check-circle" />
</span>
</span>
<div v-else>
<!-- 编辑时展示输入框 -->
<div v-if="item.isEdit">
<input type="text" v-model="item.title" class="editInput" />
<span class="tree-cancle_icon edit-require_icon">
<a-icon type="close-circle" />
</span>
<span class="tree-save_icon edit-require_icon">
<a-icon type="check-circle" />
</span>
</div>
<!-- 否则展示原来的节点信息 -->
<div v-else>
<span class="node-title">{{ item.title }} </span>
<span class="icon-wrap">
<icon name="delete" />
</span>
<span class="icon-wrap">
<icon name="edit" />
</span>
<span class="icon-wrap">
<icon name="plus" />
</span>
</div>
</div>
</template>
</a-tree>