1. 程式人生 > >elementui樹形元件的自定義增刪節點

elementui樹形元件的自定義增刪節點

elementUI樹自定義增刪改的功能

如圖所示,自定義可增刪的樹元件

  • 需求:
    • 基於vue和elementui元件的el-tree寫一個樹的樣式;
    • 可以新增和刪除當前節點;
    • 新增點選後出現彈窗,進行新增的編輯;如圖所示:
      • 點選新增節點出現彈出框
      • 彈出框樣式,輸入的名稱和標識作為樹的顯示名稱
      • 最終新增的樹的節點
    • 根據當前節點的情況確定是否需要顯示刪除和新增的圖示;例如:如果是根節點,則只能新增不能刪除;

準備

  • 新增節點思路:
    • 點選新增按鈕之後,出現彈出框;
    • 讀取使用者輸入的資訊傳遞給後臺,並且請求資料(節點id、節點名稱、節點是否可新增、節點是否可刪除等);
    • 將請求回來的資料在樹形元件上進行渲染;
  • 刪除節點思路:
    • 點選當前要刪除的節點,獲取當前id;
    • 根據當前節點id,遍歷其所有的children,在list中進行刪除;

專案使用中的注意

  • 該樹形元件是基於vue和webspack的,而elementUI中在樹的節點區新增按鈕或圖示等內容,需要使用render-content指定渲染函式;
  • 首先需要下載依賴包,此處主要講需要使用的jsx部分,需要下載以下安裝包:
npm install babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-helper-vue-jsx-merge-props babel-preset-env --save-dev
  • 然後需要配置.babelrc(此處配置很重要), 如下:
{
  "presets
": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], "plugins": ["transform-runtime","transform-vue-jsx"], "env": { "test": { "presets": ["env", "stage-2"], "plugins": ["transform-vue-jsx"
,"istanbul"]
}
}
}

原始碼

  • html
<!--樹形控制元件-->
<el-aside width="300px" style="padding: 15px;">
    <el-tree
        ref="eventCategoryTree"
        :data="eventCategoryTree"
        :props="defaultProps"
        node-key="id"
        highlight-current
        default-expand-all
        :render-content="renderContent"
        :expand-on-click-node="false">
    </el-tree>
</el-aside>

<!--新增事件節點分類彈窗-->
<el-dialog
  title="新增事件分類"
  width="25%"
  class="add-event-dialog"
  :visible.sync="addEventdialogVisible"
  size="tiny">
  <el-form ref="addEventForm" :model="addEventForm" :rules="addEventNodeRules">
    <el-form-item label="分類名稱" prop="categoryName" >
      <el-input v-model="addEventForm.categoryName"></el-input>
    </el-form-item>
    <el-form-item label="分類標識" prop="categoryFlag">
      <el-input v-model="addEventForm.categoryFlag"></el-input>
    </el-form-item>
  </el-form>
  <span slot="footer" class="dialog-footer" >
    <el-button @click="addEventFormCancleBtn('addEventForm')">取 消</el-button>
    <el-button type="primary" @click="addEventFormSubmitBtn('addEventForm')">確 定</el-button>
  </span>
</el-dialog>
  • data
//樹元件的資料
eventCategoryTree: [
 {
    id: 1,
    label: '一級 1',
    addAble: true,  //根據後臺給的是否可新增節點,也可以根據當前的node節點自行判斷
    delAble: false,  //根據後臺給的是否可刪除節點,也可以根據當前的node節點自行判斷
    parentId: '',
    children: [{
      id: 4,
      label: '二級 1-1',
      addAble: false,
      delAble: true,
      parentId: '1',
    },{
      id: 5,
      label: '二級 2-1',
      addAble: false,
      delAble: true,
      parentId: '1',
    }, {
      id: 6,
      label: '二級 2-2',
      addAble: false,
      delAble: true,
      parentId: '1',
    },]
  }],
  defaultProps: {
    children: 'children',
    label: 'label'
  },

/*觸發的當前的節點,放到全域性,方便呼叫*/
triggerCurrenNodeData:{},
/*觸發的當前節點*/
triggerCurrenNode:{},
/*新增事件彈窗的輸入框資料*/
addEventdialogVisible: false,
addEventForm:{
  categoryName: '',
  categoryFlag: '',
},
  • 引入自定義的樹:將該元件放置在同一個資料夾下以供呼叫;
    同級目錄下的樹元件
import TreeRender from './tree_render.vue';
  • methods:
/*渲染函式*/
renderContent(h, { node, data, store }) {
    let that = this;//指向vue
    return h(TreeRender,{
      props:{
        NODE: node,
        DATA: data,
        STORE: store,
      },
      on:{
        //新增
        Append: ((s,d,n) => that.appendEvent(s,d,n)),
        //刪除節點
        Delete: ((s,d,n) => that.removeEvent(s,d,n)),
        //檢視
        WatchInfo: ((s,d,n)=> that.changeMainRegion(s,d,n))
      }
    }
  );
},
/*樹形控制元件新增節點,新增彈窗出現*/
appendEvent(s,d,n) {
  this.addEventdialogVisible = true;
  this.triggerCurrenNodeData = d;
  this.triggerCurrenNode = n;
},
/*樹形控制元件刪除節點*/
removeEvent(s,d,n) {
  const parent = n.parent;
  const children = parent.data.children || parent.data;
  const index = children.findIndex(data => data.id === d.id);
  console.log(index,'索引')
  this.$confirm('確定要刪除該節點嗎?', '溫馨提示', {
    confirmButtonText: '確定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    this.$http('delete', `/url/****/****/${d.id}`,{queryParams: null})
      .then((res) => {
        if (res.statusCode === 200) {
          children.splice(index, 1);
          this.$message({
            message: res.messages[0],
            type: 'success'
          });
        }
      });
  }).catch(() => {
    this.$message({
      type: 'info',
      message: '已取消刪除'
    });
  });
},

 /*節點新增,新增樹形選單事件分類彈窗,提交按鈕*/
addEventFormSubmitBtn(formname){
  this.$refs[formname].validate((valid) => {
    if (valid) {
      console.log('驗證成功')
      /*獲取當前input上輸入的文字*/
      let dataPost={
        label: this.addEventForm.categoryName.trim(),
        id: this.addEventForm.categoryFlag.trim(),
        parentId: this.triggerCurrenNodeData.id,  //當前節點id
        depth: this.triggerCurrenNode.level, //當前節點層級
      }
      this.$http('post', '/api/***/****', {queryParams: dataPost})
        .then((res) => {
          console.log('請求成功');
          if (res.statusCode === 200) {
            let result = res.data;
            /*點選彈窗的確定按鈕可以得到輸入的資料,作為新的節點名稱插入*/
            /*如果沒有子節點,就建立一個子節點插入*/
            if (!this.triggerCurrenNodeData.children) {
              this.$set(this.triggerCurrenNodeData, 'children', []);
            };
            //如果已有子節點,就把返回的資料push進去,插入到樹形資料中
            this.triggerCurrenNodeData.children.push(result);
            /*關閉彈窗,重置輸入框*/
            this.addEventdialogVisible = false;
            this.$refs[formname].resetFields();
            /*重新整理樹形選單*/
            //this.getDictionarytTree();
          }
        })
        .catch((e) => {
           console.log('請求失敗',e)
        })
    } else {
      console.log('驗證未通過');
      return false;
    }
  });
},
  • 引入的自定義的樹元件:
<template>
      <span style="flex: 1; display: flex; align-items: center; font-size: 14px; padding-right: 8px;">
        <span @click="WatchInfo(STORE,DATA,NODE)" style="width: 80%">
          <span>{{DATA.label}}</span>
        </span>
        <span class="span_icon">
          <el-button style="font-size: 12px;" type="text" v-if="DATA.addAble" @click="Append(STORE,DATA,NODE)">
            <i class="el-icon-plus"></i>
          </el-button>
          <el-button style="font-size: 12px;" type="text" v-if="DATA.delAble" @click="Delete(STORE,DATA,NODE)">
            <i class="el-icon-delete"></i>
          </el-button>
        </span>
      </span>
</template>

<script>
  export default {
    name: '',
    data() {
        return {}
    },
    props: ['NODE', 'DATA', 'STORE'],
    methods:{
      Append(s,d,n){
        //新增節點事件
        this.$emit('Append',s,d,n)
      },
      Delete(s,d,n){
        this.$emit('Delete',s,d,n)
      },
      WatchInfo(s,d,n){
        this.$emit('WatchInfo',s,d,n)
      }
    }
  }
</script>
<style></style>