Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作


Posted in Javascript onAugust 31, 2020

需求: vue-cli项目树形控件:一级节点为本地节点,默认展开一级节点,增删改后局部刷新数据。

Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作

增加节点,点击确定后局部刷新,渲染新数据。

Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作

源码

element组件样式

<el-tree 
        class="treeitems"
        :data="data"
        node-key="id"
        :props="defaultProps" 
        :load="loadNode"
        lazy
        :default-expanded-keys="[0]"
        @node-click="handleNodeClick"
        draggable
        :allow-drop="allowDrop"
        :allow-drag="allowDrag"
         @node-drop="handleDrop"
        ref="tree"
      >
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <i @click="() => append(node,data)" class="el-icon-plus"></i><!--增加分组-->
          <!-- 根节点不需要删除和重命名 -->
          <i v-if="data.id !== 0" @click="() => deletes(node,data)" class="el-icon-delete"></i><!--删除分组-->
          <i v-if="data.id !== 0" @click="() => rename(node,data)" class="el-icon-edit"></i><!--重命名分组-->
        </span>
      </span>
     </el-tree>

data数据

data() {
   return {
    filterText: '',
    data: [{
      id:0,
      label: '中国',
      
    }],
    children: [{
        id:1,
        label: '北京',
        children: [{
          id:11,
          label: '通州'
        }]
      },
      {  
        id:2,
        label: '上海',
        leaf: true,
      },
      {  
        id:3,
        label: '山西',
        children:[{
          id: 13,
          label: '太原'
        },{
          id: 14,
          label: '阳泉'
        }]
      },{
        id:4,
        label: '黑龙江',
        children: [{
          id:12,
          label: '哈尔滨'
        }]
      }],
    defaultProps: {
     children: 'children',
     label: 'label',
     isLeaf: 'leaf'
    }
   };

点击增加节点弹出弹窗

这里也用的是element的弹窗,直接在methods里写:

//点重命名事件
 append(node,data) {
      console.log(node,data,'增加')
      this.$prompt('节点名字', '增加节点', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPattern: /^[\u4e00-\u9fa5]{0,}$/,//匹配全中文
        inputErrorMessage: '请输入中文'//不符合正则匹配的提示语句
        }).then(({ value }) => {
          //可以在这里发请求,http是我模拟的一个虚假的封装好的axios请求,()可写请求参数
          http().then((data)=>{
            this.$message({
              type: 'success',
              message: '修改成功'
            }); 
            //请求成功需局部刷新该节点,调用方法,把节点信息node传入
            this.partialRefresh(node)
          })
          //请求失败
          .catch(()=>{
            this.$message({
              type: 'info',
              message: '修改失败'
            }); 
          })
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '取消修改'
          });    
      });
    },
    //实现局部刷新,在点击弹窗处调用的
    partialRefreshpartialRefresh(node){
      //设置loaded为false;模拟一次节点展开事件,加载重命名后的新数据;
      node.loaded = false;
      node.expand(); 
      //新建子节点是刷新一次本节点的展开请求,而重命名和删除则需要刷新父级节点的的展开事件,
      //可以设置node.parent.loaded = false;node.parent.expand();
    },

懒加载

Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作

该处可直接设置有无节点,如果后端返回有无节点的表示就可用,若无可舍弃。(data中写,我在本地模拟数据上海字段中加了leaf: true,上海节点就默认没有节点了)

//懒加载
    loadNode(node, resolve){
      if (node.level === 0) {
        //本地的数据,一个承载中国字样的数组;
        return resolve(this.data);
      }
      else if(node.level === 1){
        //现在为模拟数据;
        //有真实数据,在resolve中放置请求回来的数据即可。
        //else同样也是。我这里是区分了两种请求方式。
        return resolve(this.children)
      }
      else{
        return resolve([])
      }
    },

拖拽节点

//拖拽==>拖拽时判定目标节点能否被放置
    allowDrop(draggingNode, dropNode, type){
      //参数:被拖拽节点,要拖拽到的位置
      //因为根目录是我本地写死的,不能有同级,所以我设置凡是拖拽到的level===1都存放到根节点的下面;
      if(dropNode.level===1){
        return type == 'inner';
      }
      else {
        return true;
      }
    },
    //拖拽==>判断节点能否被拖拽
    allowDrag(draggingNode){
     //第一级节点不允许拖拽
      return draggingNode.level !== 1;
    },

需求改了,同级节点拖拽,拖拽完成后将排序结果返回后端:

//拖拽==>拖拽时判定目标节点能否被放置
    //后更改为只能同级拖拽
    allowDrop(draggingNode, dropNode, type) {
      if (draggingNode.level === dropNode.level) {
        if (draggingNode.data.parentId === dropNode.data.parentId) {
          return type === 'prev' || type === 'next'
        }
      } else {
        // 不同级不允许拖拽
        return false
      }
    },
    //拖拽==>判断节点能否被拖拽
    allowDrag(draggingNode) {
      return draggingNode.level !== 1;
    },
    //拖拽成功完成时触发的事件,在这里可以将节点拖拽后的顺序返给后端
    handleDrop(node,data,type,event){
      let arr=[];
      //data为拖拽后节点信息,找到它的父级,在从父级找子集
      let child = data.parent.childNodes;
      for(var key in child){
        arr.push({id:child[key].data.id})
      }
      //转为JSON字符串发请求带走信息
      idSort(JSON.stringify(arr))
    }

补充知识:vue+element tree ----增加修改删除上下移动

<template>
 <div>
  <div class="exam_structure">
   <el-input
    placeholder="输入关键字进行过滤"
    v-model="filterText">
   </el-input>
 
 
   <el-button type="primary" size="small" class="add_new_question" @click="add_new_question"><i></i>添加父节点</el-button>
 
  </div>
 
  <div class="question_info_lists">
 
   <el-tree ref="tree" :key="tree_key" :data="treeData" node-key="id" :render-content="renderContent"
        :expand-on-click-node="false" :default-expanded-keys="defaultExpand" show-checkbox
        :filter-node-method="filterNode"></el-tree> 
 
   <el-row class="add_question" v-show="add_question_flag">
 
    <el-col :span="12">
 
     <el-input v-model="new_question_name" placeholder="请输入大题名称"></el-input>
 
    </el-col>
 
    <el-col :span="12">
 
     <el-button size="mini" class="btn_sure" @click.stop="add_question_sure">确定</el-button>
 
     <el-button size="mini" class="btn_cancel" @click.stop="add_question_cancel">取消</el-button>
 
    </el-col>
 
   </el-row>
 
  </div>
 </div>
</template>
 
<script>
 export default {
  name: "tree1",
 
  watch: {
   filterText(val) {
    this.$refs.tree.filter(val);
   }
  }, 
 
  methods: {
   filterNode(value, data) {
    if (!value) return true;
    return data.label.indexOf(value) !== -1;
   },
// 添加新大题
 
   add_new_question() { 
    this.add_question_flag = true 
   },
 
   add_question_sure() {  //确定
 
    const nodeObj = {id: '', label: this.new_question_name, isEdit: false, children: []}
    this.treeData.push(nodeObj)
    this.add_question_flag = false
 
   },
 
   add_question_cancel() {  //取消 
    this.add_question_flag = false 
    this.new_question_name = '' 
   },
 
   //   增加
   append(store, node, data) {
    var maxid = '20'
    //新增数据
    const nodeapp = {id: ++maxid, label: '增加节点', isEdit: false, children: []}
    data.children.push(nodeapp)
    if (!node.expanded) {
     node.expanded = true
    }
    const parent = node.parent
    const children = parent.data
    const cIndex = children.findIndex(d => d.id === data.id)
    const tempChildrenNodex2 = children[cIndex] //拿到被添加的上一级
    console.log(tempChildrenNodex2.children[cIndex - 1])
   },
 
// 修改
 
   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.label = $input.value 
     data.isEdit = false 
    } 
   },
 
// 节点删除 
   nodeDelete(node, 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) 
   },
 
// 节点上移
 
   nodeUp(node, data) { 
    const parent = node.parent 
    const children = parent.data.children || parent.data 
    const cIndex = children.findIndex(d => d.id === data.id) 
    if (parent.level === 0 && cIndex === 0) { 
     return 
    } else if (parent.level !== 0 && cIndex === 0) { //不同父节点中移动
     alert('不同父节点中移动')
 
     // const parent2 = parent.parent 
     // const children2 = parent2.data.children || parent2.data 
     // const pIndex2 = parseInt(children2.findIndex(p => p.id === parent.data.id), 10) - 1 
 
     // if (pIndex2 < 0) return 
     // children2[pIndex2].children.push(data) 
     // children.splice(cIndex, 1)
 
     // this.defaultExpand[0] = children2[pIndex2].id
 
    } else if ((parent.level === 0 && cIndex !== 0) || (parent.level !== 0 && cIndex !== 0)) {
 
     const tempChildrenNodex1 = children[cIndex - 1] 
     const tempChildrenNodex2 = children[cIndex] 
     this.$set(children, cIndex - 1, tempChildrenNodex2) 
     this.$set(children, cIndex, tempChildrenNodex1) 
     this.defaultExpand[0] = data.id 
    }
 
    this.tree_key++ 
   },
 
// 节点下移
 
   nodeDown(store, node, data) { 
    const parent = node.parent
    const children = parent.data.children || parent.data
    const cIndex = children.findIndex(d => d.id === data.id)
    const cLength = children.length - 1 // 最边上的节点
    const allLevel = store.data.length - 1 // 树的深度 
 
    if (parent.level === allLevel && cIndex === cLength) { // 最最末的节点
 
     return
 
    } else if (parent.level !== allLevel && cIndex === cLength) { //父节点不同
     alert('不能移动')
     // const parent2 = parent.parent
 
     // const children2 = parent2.data.children || parent2.data
 
     // const pIndex2 = parseInt((children2.findIndex(p => p.id === parent.data.id)), 10) 
 
     // if (pIndex2 === allLevel) return
 
     // children2[pIndex2 + 1].children.push(data)
 
     // children.splice(cIndex, 1)
 
     // this.defaultExpand[0] = children2[pIndex2 + 1].id
 
    } else if ((parent.level === allLevel && cIndex !== cLength) || (parent.level !== allLevel && cIndex !== cLength)) { // 父节点相同
 
     const tempChildrenNodex1 = children[cIndex + 1] 
     const tempChildrenNodex2 = children[cIndex] 
 
     this.$set(children, cIndex + 1, tempChildrenNodex2) 
     this.$set(children, cIndex, tempChildrenNodex1) 
     this.defaultExpand[0] = data.id 
    } 
    this.tree_key++ 
   },
 
   showOrEdit(data) { 
    if (data.isEdit) { 
     return <input type="text" value={data.label} on-blur={ev => this.edit_sure(ev, data)}/> 
    } else { 
     return <span className="node_labe">{data.label}</span> 
    } 
   },
 
// 结构树操作group node, 
   renderContent(h, {node, data, store}) { 
    return ( 
     <span> 
<span class="el-icon-document"> 
{this.showOrEdit(data)} 
</span> 
<div class="tree_node_op" style=" float: right"> 
<i class="el-icon-edit" on-click={(ev) => this.nodeEdit(ev, store, data)}></i> 
<i class="el-icon-delete" on-click={() => this.nodeDelete(node, data)}></i> 
<i class="el-icon-upload2" on-click={() => this.nodeUp(node, data)}></i> 
<i class="el-icon-download" on-click={() => this.nodeDown(store, node, data)}></i>
<i class="el-icon-plus" on-click={() => this.append(store, node, data)}></i>
 
</div> 
</span>) 
   } 
  }
  , data() { 
   return {
    filterText: '',
    treeData: [{
 
     id: 1, 
     label: '一级 1', 
     isEdit: false, 
     children: [{ 
      id: 4, 
      label: '二级 1-1', 
      isEdit: false, 
      children: [{id: 9, label: '三级 1-1-1', isEdit: false, children: []}, {
       id: 10,
       label: '三级 1-1-2',
       isEdit: false,
       children: []
      }, {
       id: 11,
       label: '三级 1-1-3',
       isEdit: false,
    children: []
      }] 
     },
 
      { 
       id: 12, 
       label: '二级 1-2', 
       isEdit: false, 
       children: [] 
      },
 
      { 
       id: 13, 
       label: '二级 1-3', 
       isEdit: false, 
       children: [] 
      }] 
    },
 
     { 
      id: 2, 
      label: '一级 2', 
      isEdit: false,
       children: [{id: 5, label: '二级 2-1', isEdit: false, children: []}, {
       id: 6,
       label: '二级 2-2',
       isEdit: false,
       children: []
      }] 
     },
 
     { 
      id: 3, 
      label: '一级 3', 
      isEdit: false, 
      children: [
       {id: 7, label: '二级 3-1', isEdit: false, children: []},
       {
       id: 8,
       label: '二级 3-2',
       isEdit: false,
       children: []
      }] 
     }],
 
    add_question_flag: false, 
    new_question_name: '', 
    tree_key: 0, 
    defaultExpand: [] 
   } 
  }, 
 }
</script> 
<style scoped> 
</style>

Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作

以上这篇Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js类 from qq
Nov 13 Javascript
jquery学习总结(超级详细)
Sep 04 Javascript
Javascript对象Clone实例分析
Jun 09 Javascript
JavaScript中字面量与函数的基本使用知识
Oct 20 Javascript
Javascript模仿淘宝信用评价实例(附源码)
Nov 26 Javascript
VUEJS实战之构建基础并渲染出列表(1)
Jun 13 Javascript
Javascript 实现微信分享(QQ、朋友圈、分享给朋友)
Oct 21 Javascript
荐书|您有一份JavaScript书单待签收
Jul 21 Javascript
vue弹窗插件实战代码
Sep 08 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 Javascript
js实现移动端tab切换时下划线滑动效果
Sep 08 Javascript
jQuery实现简单评论功能
Aug 19 jQuery
JS遍历树层级关系实现原理解析
Aug 31 #Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
Aug 31 #Javascript
Vue循环中多个input绑定指定v-model实例
Aug 31 #Javascript
浅析 Vue 3.0 的组装式 API(一)
Aug 31 #Javascript
vue中v-model对select的绑定操作
Aug 31 #Javascript
Vue v-for中的 input 或 select的值发生改变时触发事件操作
Aug 31 #Javascript
vue绑定数字类型 value为数字的实例
Aug 31 #Javascript
You might like
如何写php程序?
2006/12/08 PHP
Gregarius中文日期格式问题解决办法
2008/04/22 PHP
PHP图片验证码制作实现分享(全)
2012/05/10 PHP
PHP下载远程图片的几种方法总结
2017/04/07 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
2019/03/11 PHP
基于PHP实现生成随机水印图片
2020/12/09 PHP
javascript 读取图片文件的大小
2009/06/25 Javascript
javascript中键盘事件用法实例分析
2015/01/30 Javascript
javascript实现输出指定行数正方形图案的方法
2015/08/03 Javascript
封装的dialog插件 基于bootstrap模态对话框的简单扩展
2016/08/10 Javascript
JS封装的选项卡TAB切换效果示例
2016/09/20 Javascript
jquery实现多次上传同一张图片
2017/01/09 Javascript
js模拟微博发布消息
2017/02/23 Javascript
自定义事件解决重复请求BUG的问题
2017/07/11 Javascript
vue 动态设置img的src地址无效,npm run build 后找不到文件的解决
2020/07/26 Javascript
python3中set(集合)的语法总结分享
2017/03/24 Python
利用Python找出序列中出现最多的元素示例代码
2017/12/08 Python
Python 统计字数的思路详解
2018/05/08 Python
Python使用pickle模块实现序列化功能示例
2018/07/13 Python
深入flask之异步非堵塞实现代码示例
2018/07/31 Python
Python爬虫小技巧之伪造随机的User-Agent
2018/09/13 Python
python读取word文档,插入mysql数据库的示例代码
2018/11/07 Python
浅谈Python中re.match()和re.search()的使用及区别
2020/04/14 Python
Python延迟绑定问题原理及解决方案
2020/08/04 Python
python 爬取B站原视频的实例代码
2020/09/09 Python
全面解析HTML5中的标准属性与自定义属性
2016/02/18 HTML / CSS
生产厂厂长岗位职责
2013/12/25 职场文书
自我评价格式
2014/01/06 职场文书
会议邀请书范文
2014/02/02 职场文书
大学生党员自我评价范文
2014/04/09 职场文书
竞聘演讲稿精彩开头和结尾
2014/05/14 职场文书
夏季药店促销方案
2014/08/22 职场文书
2014最新离职证明范本
2014/09/12 职场文书
2014年生产部工作总结
2014/12/17 职场文书
高中家长意见怎么写
2015/06/03 职场文书
golang内置函数len的小技巧
2021/07/25 Golang