1. 程式人生 > 實用技巧 >vue-antd tree元件自定義增刪改功能

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>