在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>