欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue实现树形结构增删改查的示例代码

程序员文章站 2022-03-23 22:57:26
其实很多公司都会有类似于用户权限树的增删改查功能,正好最近我刚写了一个树形结构的增删改,在这里和大家分享一下,如果有不合理的地方欢迎评论,我会尽快优化~~ 先附上一下效果图这个是没有点击编辑时,产品的...

其实很多公司都会有类似于用户权限树的增删改查功能,正好最近我刚写了一个树形结构的增删改,在这里和大家分享一下,如果有不合理的地方欢迎评论,我会尽快优化~~ 先附上一下效果图

这个是没有点击编辑时,产品的需求是选中某个节点,取得该节点对应的设备数据,所以初始页面是下面这个样子的。

vue实现树形结构增删改查的示例代码

这个是点击了编辑之后,显示节点的编辑按钮

vue实现树形结构增删改查的示例代码

点击最上面的添加按钮,显示最外层父节点的添加画面

vue实现树形结构增删改查的示例代码

修改节点名称

vue实现树形结构增删改查的示例代码

因为我们的需求是编辑与非编辑两种状态,所以我用了两个树形组件,通过v-if进行控制。(v-if:该组件不存在,v-show:组件占用空间,只是不展示)

<el-tree
    v-if="treesetdata.editflg"
     ref="tree"
     :key="treesetdata.tree_key"
     :data="treesetdata.treedata"
     node-key="id"
     :render-content="rendercontent"
     :expand-on-click-node="false"
     :default-expand-all="treesetdata.defaultexpandall"
     highlight-current
     @node-click="handlenodeclick"
     class="tree-style"
 ></el-tree>
 <el-tree
     v-else
     ref="tree"
     :key="treesetdata.tree_key"
     :data="treesetdata.treedata"
     node-key="id"
     :render-content="rendercontent"
     :expand-on-click-node="false"
     :default-expand-all="treesetdata.defaultexpandall"
     highlight-current
     class="tree-style"
 ></el-tree>

树形组件的字段说明我就不一一赘述了,可以通过element-ui的树形组件官网查看,但是我要单独说明一下以下方法,

  • render-content:自定义节点内容,rendercontent:为方法名。
  • @node-click:节点点击时调用,因为只有在非编辑状态下才存在节点点击效果,因此该方法我只写在了非编辑的树形组件内

所需data说明

// 树形结构所需数据  
treesetdata:{
  defaultexpandall:true, // 是否默认展开
  editflg:true, // 是否是编辑状态
  treedata: [], // 树形组件数据集
  // 编辑树形数组内容
  editlist:[],
  // 删除树形数据数组内容
  deletelist:[],
  // 添加树形数据数组内容
  addlist:[],
  // 是否添加flg
  addnodeflg:false,
  // 默认的id
  defaultid:5000,
  // 新增的最外层节点名称
  newname:'',
  tree_key: 0,
},

说明一下最外层节点的添加方法,其实主要的核心思想是控制下方的输入框以及按钮的展示与否,然后点击确认按钮之后,在原有的树形组件data里新增一条数据。

实现画面

vue实现树形结构增删改查的示例代码

添加按钮的html代码

<el-button type="text" @click="add_new_area" class="button-style"><i class="el-icon-plus" style="margin-right:5px"></i>添加</el-button>

添加按钮点击方法【add_new_area】

add_new_area() {
      this.treesetdata.addnodeflg = true;
    },

文本框的代码片段

<el-row class="add_question" v-show="treesetdata.addnodeflg">
    <el-col :span="11" style="margin:0px 5px">
         <el-input v-model="treesetdata.newname" placeholder="通行区域" size="mini"></el-input>
     </el-col>
     <el-col :span="12">
         <el-button size="mini" type="primary" plain @click.stop="add_area_sure">确定</el-button>
         <el-button size="mini" type="warning" plain @click.stop="add_area_cancel">取消</el-button>
     </el-col>
 </el-row>

确认按钮【add_area_sure】

add_area_sure() {
// 添加节点数据,因为是最上层,所以默认父id是pid,id的话是我初始化设置的【defaultid】的自加,大家自己在data中加一下【defaultid】字段就可以了
  const nodeobj = {
    id: this.treesetdata.defaultid++,
    name: this.treesetdata.newname,
    isedit: false,
    children: [],
    pid:0
  };
  this.treesetdata.treedata.push(nodeobj);
  this.treesetdata.addnodeflg = false;
  this.treesetdata.addlist.push(nodeobj);
},

取消按钮【add_area_cancel】

add_area_cancel() {
  this.treesetdata.addnodeflg = false;
  this.treesetdata.newname = "";
},

至此就可以实现最外层节点的添加了。

编辑状态下的几点增删改的话,其实就是通过自定义节点内容的【rendercontent】这个方法实现的,快下班了我就不一一说明了,有时间再补吧,先把主要代码提出来~

// 通行区域树操作group node,
    rendercontent(h, { node, data, store }) {
        if(this.treesetdata.editflg == false){
            return (
                <span class="tree-span">
                    <span>{this.showoredit(data)}</span>
                    <div class="tree_node_op">
                        <i class="el-icon-edit" on-click={ev => this.nodeedit(ev, store, data)} style="padding-left: 10px;"></i>
                        <i class="el-icon-circle-plus" on-click={() => this.nodeadd(node, data)} style="margin-left: 5px;"></i>
                        <i class="el-icon-remove" on-click={() => this.nodedelete(node, data)} style="margin-left: 5px;"></i>
                    </div>
                </span>
            );
        } else {
            return (
                <span class="tree-span">
                    <span>{this.showoredit(data)}</span>
                    <div class="tree_node_op">
                    </div>
                </span>
            );
        }
    },

    // 节点编辑
    showoredit(data) {
      if (data.isedit) {
        return (
          <el-input
            type="text"
            value={data.name}
            on-blur={ev => this.edit_sure(ev, data)}
            size="mini"
            class="input-style"
          ></el-input>
        );
      } else {
        return <span classname="node_labe">{data.name}</span>;
      }
    },
    nodeedit(ev, store, data) {
      data.isedit = true;
      this.$nexttick(() => {
        const $input =
          ev.target.parentnode.parentnode.queryselector("input") ||
          ev.target.parentelement.parentelement.queryselector("input");
        !$input ? "" : $input.focus();
      });
    },

    // 确认编辑
    edit_sure(ev, data) {
        const $input =
            ev.target.parentnode.parentnode.queryselector("input") ||
            ev.target.parentelement.parentelement.queryselector("input");
        if (!$input) {
            return false;
        } else {
            data.name = $input.value;
            data.isedit = false;
        }
        // 修改编辑树形数据的内容
        let editfilter = this.treesetdata.editlist.filter((item)=>item.id == data.id);
        if (editfilter.length == 0){
            this.treesetdata.editlist.push(data);
        } else {
            this.treesetdata.editlist.foreach((item,i)=>{
                if(item.id == data.id) {
                    this.treesetdata.editlist[i].name = data.name;
                }
            })
        }
    },

    // 增加节点
    nodeadd(node, data) {
      if (data.pid !== 0){
        this.$message({type:'error',message:'通行区域最多只能有两级层次结构。'});
        return false;
      } else {
          const newchild = { id: this.treesetdata.defaultid++, name: '新增的通行区域', isedit:false, pid:data.id, children: [] };
          if (!data.children) {
            this.$set(data, 'children', []);
          }
          data.children.push(newchild);
          this.treesetdata.addlist.push(newchild);
      }
    },

    // 节点删除
    nodedelete(node, data) {
      this.treesetdata.deletelist.push(data);
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const index = children.findindex(d => d.id === data.id);
      children.splice(index, 1);
    },

然后将上面处理完的数据(要增加的数据:addlist,要修改的数据:editlist,要删除的数据:deletelist)整体提交给后台去做数据库处理就可以了,但是需要注意一下以下的几种情况。

// 先添加,后修改的数据整合
this.treesetdata.addlist.foreach((item,i)=>{
    let editfilter = this.treesetdata.editlist.filter((value)=>value.id == item.id);
    if(editfilter.length !== 0){
        this.treesetdata.addlist[i] = editfilter[0];
        this.treesetdata.editlist = this.treesetdata.editlist.filter((value)=>value.id !== item.id);
    }
})
// 先添加,后删除的数据整合
this.treesetdata.deletelist.foreach((item,i)=>{
    let addfilter = this.treesetdata.addlist.filter((value)=>value.id == item.id);
    if(addfilter.length !== 0){
        this.treesetdata.deletelist = this.treesetdata.deletelist.filter((value)=>value.id !== item.id);
        this.treesetdata.addlist = this.treesetdata.addlist.filter((value)=>value.id !== item.id);
    }
})
// 先编辑,后删除的数据整合
this.treesetdata.deletelist.foreach((item,i)=>{
    let editfilter = this.treesetdata.editlist.filter((value)=>value.id == item.id);
    if(editfilter.length !== 0){
        this.treesetdata.editlist = this.treesetdata.editlist.filter((value)=>value.id !== item.id);
    }
})

树形组件样式

<style lang="less">
.el-message-box {width: 450px;}
.button-style {padding: 0px}
.input-style {height: 15px;width: 140px;}
.through-panel-body {
  padding-top:12px;
  width: 100%;
  display: flex;
  .panel-area-left {
    position: relative;
    width: 360px;
    border:2px solid rgba(240,240,240,1);
    border-radius: 5px;
    .head-title {
        display:flex;justify-content: space-between;padding:10px 10px;
        h5{border-left:solid 3px #fb8742;padding-left:5px;height: 20px;line-height:20px;font-size:16px;}
    }
    .area-tree {
        width: 100%;
        .tree-style {
            margin: 0px 0px 10px 10px;
            height:88%;
            overflow-y: auto;
        }
        .el-tree-node__content { 
            padding-left: 10px;display: flex;width: 100%; 
            .tree-span {
                display: flex; width: 100%; 
                .tree_node_op {
                    margin-left: 10px;color: #d3d3d3;
                }
            }
        }
    }
    .add_question {
        margin: 10px 0px;
    }
    .foot-style{
        padding-right:5px; 
        height: 40px;
        text-align: right;
    }
  }
  .panel-area-right {
    margin-right: 5px;
    width: 100%;
    padding-left: 15px;
    height: 100%;
    .el-row {
      width: 100%;
      display: flex;
      justify-content: space-between;
      .located-class {
        width: 50%;
      }
      .device-floor-class {
        width: 50%;
        display: flex;
        justify-content: flex-end;
      }
    }
  }
}
</style>

到此这篇关于vue实现树形结构增删改查的示例代码的文章就介绍到这了,更多相关vue 树形结构增删改查内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!