elementUI树自定义增删改的功能

如图所示,自定义可增删的树组件

  • 需求:
    • 基于vue和elementui组件的el-tree写一个树的样式;
    • 可以添加和删除当前节点;
    • 添加点击后出现弹窗,进行添加的编辑;如图所示:
      • 点击新增节点出现弹出框
      • 弹出框样式,输入的名称和标识作为树的显示名称
      • 最终新增的树的节点
    • 根据当前节点的情况确定是否需要显示删除和添加的图标;例如:如果是根节点,则只能添加不能删除;

准备

  • 参考文档:https://segmentfault.com/a/1190000011574698
  • 新增节点思路:
    • 点击新增按钮之后,出现弹出框;
    • 读取用户输入的信息传递给后台,并且请求数据(节点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>
Logo

前往低代码交流专区

更多推荐