首页 > 编程 > JavaScript > 正文

VUE饿了么树形控件添加增删改功能的示例代码

2019-11-19 15:09:03
字体:
来源:转载
供稿:网友

本文介绍了VUE饿了么树形控件添加增删改功能的示例代码,分享给大家,具体如下:

element-ui树形控件:地址

在原文档中有个案例是有新增和删除功能,但是后来发现其修改的数据并不能直接影响到树形数据,所以采用了 render-content 的API重新写了个组件。

写个开发的步骤,所以文章比较长emmm

大致效果如图:

1.省市API

在网上复制了个省市的list,有两个属性是新增的

  • isEdit :控制编辑状态
  • maxexpandId :为现下id的最大值
export default{  maxexpandId: 95,  treelist: [{     id: 1,     name: "北京市",     ProSort: 1,     remark: "直辖市",    pid: '',    isEdit: false,    children: [{      id: 35,      name: "朝阳区",      pid: 1,      remark: '',      isEdit: false,      children: []    }]  }{...}]}

2.el-tree Component基本

咱们一步步来,先写个饿了么的组件

<template>  <el-tree ref="expandMenuList" class="expand-tree"    v-if="isLoadingTree"    :data="setTree"    node-key="id"    highlight-current    :props="defaultProps"    :expand-on-click-node="false"    :render-content="renderContent"    :default-expanded-keys="defaultExpandKeys"></el-tree></template><!--* highlight-current :为了点击时节点高亮* expand-on-click-node : 只能箭头控制树形的展开收缩* render-content : 节点渲染方式* default-expanded-keys :默认展开节点-->

同时引入API和节点渲染的组件

import TreeRender from '@/components/tree_render'import api from '@/resource/api'

然后搭建好基础

data(){ return{  maxexpandId: api.maxexpandId,//新增节点开始id  non_maxexpandId: api.maxexpandId,//新增节点开始id(不更改)  isLoadingTree: false,//是否加载节点树  setTree: api.treelist,//节点树数据  defaultProps: {   children: 'children',   label: 'name'  },  defaultExpandKeys: [],//默认展开节点列表 }},

添加个渲染的method

methods: {  renderContent(h,{node,data,store}){   let that = this;//指向vue   return h(TreeRender,{    props: {     DATA: data,//节点数据     NODE: node,//节点内容     STORE: store,//完整树形内容    },    on: {//绑定方法     nodeAdd: ((s,d,n) => that.handleAdd(s,d,n)),     nodeEdit: ((s,d,n) => that.handleEdit(s,d,n)),     nodeDel: ((s,d,n) => that.handleDelete(s,d,n))    }   });  },  handleAdd(s,d,n){//增加节点   console.log(s,d,n)  },  handleEdit(s,d,n){//编辑节点   console.log(s,d,n)  },  handleDelete(s,d,n){//删除节点   console.log(s,d,n)  }}

3.tree_render Component基本

渲染组件:

<template>  <span class="tree-expand">    <span class="tree-label">      <span>{{DATA.name}}</span>    </span>    <span class="tree-btn">      <i class="el-icon-plus" @click.stop="nodeAdd(STORE,DATA,NODE)"></i>      <i class="el-icon-edit" @click.stop="nodeEdit(STORE,DATA,NODE)"></i>      <i class="el-icon-delete" @click.stop="nodeDel(STORE,DATA,NODE)"></i>    </span>  </span></template>

添加好几个按钮(element-ui自带icon:地址)对应的方法:

export default{  props: ['NODE', 'DATA', 'STORE'],  methods: {   nodeAdd(s,d,n){//新增    this.$emit('nodeAdd',s,d,n)   },   nodeEdit(s,d,n){//编辑    this.$emit('nodeEdit',s,d,n)   },   nodeDel(s,d,n){//删除    this.$emit('nodeDel',s,d,n)   }  }}

4.改

我们用isEdit来切换input和span的显示状态,首先加个input:

<!-- tree_render component --><template>  <span class="tree-expand">    <span class="tree-label" v-if="DATA.isEdit">      <el-input class="edit" size="mini"      :ref="'treeInput'+DATA.id"      v-model="DATA.name"></el-input>    </span>    <template v-else>      <span class="tree-label">        <span>{{DATA.name}}</span>      </span>      <span class="tree-btn" v-show="!DATA.isEdit">        <i class="el-icon-plus" @click.stop="nodeAdd(STORE,DATA,NODE)"></i>        <i class="el-icon-edit" @click.stop="nodeEdit(STORE,DATA,NODE)"></i>        <i class="el-icon-delete" @click.stop="nodeDel(STORE,DATA,NODE)"></i>      </span>    </template>  </span></template>

编辑的时候按钮同时消失,那么什么时候编辑完成呢?

  • 编辑完按enter键=》监听input的enter输入
  • 点击其他节点=》input失焦-blur=》编辑时自动聚焦-focus
  • 点击当前节点范围

当以上三点发生一项,节点对应的data都要isEdit = false;

1、enter键

<!-- tree_render component --><el-input @keyup.enter.native="nodeEditPass(STORE,DATA,NODE)"></el-input>

添加方法:

//tree_render componentmethods: {  nodeEditPass(s,d,n){    d.isEdit = false;  }}

2、focus or blur

<!-- tree_render component --><el-input @blur="nodeEditPass(STORE,DATA,NODE)"></el-input>

后来发现第一次编辑时能让input聚焦,点击第二个input就不起作用了,加了autofocus属性也同样如此。所以我们要在点击编辑icon的时候,用原生的input autofocus。

修改方法:

//tree_render componentnodeEdit(s,d,n){//编辑 d.isEdit = true; this.$nextTick(() => {  this.$refs['treeInput'+d.id].$refs.input.focus() }) this.$emit('nodeEdit',s,d,n)}

3、当前节点点击

采用el-tree已有的API――node-click

<!-- el-tree component --><el-tree @node-click="handleNodeClick"></el-tree>

添加methods:

//el-tree componentmethods: {  handleNodeClick(d,n,s){//点击节点   d.isEdit = false;//放弃编辑状态  }}

问题来了,如果在编辑状态下点击此节点也同样会影响input,这就无法进入编辑,所以要阻止input事件冒泡:

<!-- tree_render component --><el-input @click.stop.native="nodeEditFocus"></el-input>

添加methods:

//tree_render componentmethods: {  nodeEditFocus(){}}

4、v-show代替v-if

这里有个新的问题,当用户经常编辑修改,v-if模板的开销更高,所以改用v-show。而后者不支持template模板,所以要适当调整一下位置:

<template>  <span class="tree-expand">    <span class="tree-label" v-show="DATA.isEdit">      <el-input class="edit" size="mini" autofocus      v-model="DATA.name"      :ref="'treeInput'+DATA.id"      @click.stop.native="nodeEditFocus"      @blur="nodeEditPass(STORE,DATA,NODE)"      @keyup.enter.native="nodeEditPass(STORE,DATA,NODE)"></el-input>    </span>    <span v-show="!DATA.isEdit">      <span>{{DATA.name}}</span>    </span>    <span class="tree-btn" v-show="!DATA.isEdit">      <i class="el-icon-plus" @click.stop="nodeAdd(STORE,DATA,NODE)"></i>      <i class="el-icon-edit" @click.stop="nodeEdit(STORE,DATA,NODE)"></i>      <i class="el-icon-delete" @click.stop="nodeDel(STORE,DATA,NODE)"></i>    </span>  </span></template>

5.增

新增节点 =》添加一条数据

  1. 新增的同时展开父节点
  2. 是否考虑无限新增
//el-tree componenthandleAdd(s,d,n){//增加节点 console.log(s,d,n) if(n.level >=6){  this.$message.error("最多只支持五级!")  return false; } //添加数据 d.children.push({  id: ++this.maxexpandId,  name: '新增节点',  pid: d.id,  isEdit: false,  children: [] }); //展开节点 if(!n.expanded){  n.expanded = true; }}

新增节点字体加粗 =》给节点添加一个class =》 如何判断是否新增?

我们有一个参数maxexpandId

tree_render添加一个prop

//el-tree componentrenderContent(h,{node,data,store}){//加载节点 let that = this; return h(TreeRender,{  props: {   ...   maxexpandId: that.non_maxexpandId  },  on: {...} });}

根据id判断:

//tree_render componentprops: ['NODE', 'DATA', 'STORE', 'maxexpandId']
<!-- tree_render component --><span v-show="!DATA.isEdit" :class="[DATA.id > maxexpandId ? 'tree-new tree-label' : 'tree-label']":ref="'treeLabel'+DATA.id">  <span>{{DATA.name}}</span></span>.tree-expand .tree-label.tree-new{  font-weight:600;}

6.删

跟新增同义:删除节点 =》删除一条数据

  • 新增节点直接删除
  • 已有节点需提示再删除
  • 已有子级节点不能删除
handleDelete(s,d,n){//删除节点 console.log(s,d,n) let that = this; //有子级不删除 if(d.children && d.children.length !== 0){  this.$message.error("此节点有子级,不可删除!")  return false; }else{  //删除操作  let delNode = () => {   let list = n.parent.data.children || n.parent.data,   //节点同级数据,顶级节点时无children    _index = 99999;//要删除的index   list.map((c,i) => {    if(d.id == c.id){     _index = i;    }   })   let k = list.splice(_index,1);   //console.log(_index,k)   this.$message.success("删除成功!")  }  let isDel = () => {   that.$confirm("是否删除此节点?","提示",{    confirmButtonText: "确认",    cancelButtonText: "取消",    type: "warning"   }).then(() => {    delNode()//此处可通过ajax做删除操作   }).catch(() => {    return false;   })  }  //新增节点直接删除,否则要通过请求数据删除  d.id > this.non_maxexpandId ? delNode() : isDel() }}

7.拓展

还有一些特别的需求,例如:

1、点击高亮的时候显示icon

.expand-tree .is-current>.el-tree-node__content .tree-btn,.expand-tree .el-tree-node__content:hover .tree-btn{ display: inline-block;}

2、添加顶级节点

添加按钮:

<!-- el-tree component --><el-button @click="handleAddTop">添加顶级节点</el-button>

添加methods:

//el-tree componentmethods: { handleAddTop(){  this.setTree.push({   id: ++this.maxexpandId,   name: '新增节点',   pid: '',   isEdit: false,   children: []  }) }}

3、默认展开树形第一级

//el-tree componentmounted(){ this.initExpand()},methods: { initExpand(){  //isLoadingTree用意也是在此  this.setTree.map((a) => {   this.defaultExpandKeys.push(a.id)  });  this.isLoadingTree = true; },}

8.github

还有些具体的样式都放在github

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表