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

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

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

源码

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();
    },

懒加载

该处可直接设置有无节点,如果后端返回有无节点的表示就可用,若无可舍弃。(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自定义增删改和局部刷新及懒加载操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Vue加载组件、动态加载组件的几种方式

    什么是组件: 组件是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.在较高层面上,组件是自定义的元素,Vue.js的编译器为它添加特殊功能.在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展. 下面一段简单的代码给大家介绍Vue加载组件的几种方式,具体代码如下所示: //正常加载 import index from '../pages/index.vue' import view from '../pages/view.vue' //懒加载 const i

  • Element-ui el-tree新增和删除节点后如何刷新tree的实例

    一, 当新增节点后刷新当前节点 node.loaded = false; node.expand(); //新建子节点是刷新一次本节点的展开请求,而重命名和删除则需要刷新父级节点的的展开事件, 二, 删除节点 node.parent.loaded = false node.parent.expand() 完毕~ 补充知识:element-ui组件el-tree添加按钮管用,删除按钮,数据会变,但是页面不更新 可能是element-ui 的版本太低了 我用的element-ui 2.4.6 后来发

  • Element-ui tree组件自定义节点使用方法代码详解

    工作上使用到element-ui tree 组件,主要功能是要实现节点拖拽和置顶,通过自定义内容方法(render-content)渲染树代码如下~ <template> <div class="sortDiv"> <el-tree :data="sortData" draggable node-key="id" ref="sortTree" default-expand-all :expand-

  • ElementUI中el-tree节点的操作的实现

    其实tree的有些方法用起来是很方便的, this.$refs.tree.getCheckedKeys():这个原生态的方法.官方文档上说的是,返回一个数组.有了这个方法,我们就可以得到选中的每个节点的id,拿到了id,那所有的问题就迎刃而解了. 废话不多说,直接上代码 html <div id="app"> <el-row> <el-button @click="checkedKeys">得到节点id</el-button

  • vue动态加载SVG文件并修改节点数据的操作代码

    先上一个马赛克图片叭. 接领导需求,动态实现电路图, 并附带放大.缩小功能. 以及不同的回路点击能弹窗显示相关节点的更多信息, 通俗一点讲: 随着用户点击放大和缩小, 点击位置保持不变,而且能实现点击交互. 初接触的时候,觉得根本没法下手呀,说说自己的思路叭, 从随着用户点击放大缩小位置不变,想到了SVG 但是需要动态加载进来呀,而且还需要需求不同节点的电流值, 从放大缩小来看, 首先想到的是 D3 在集合领导给的部分相关资料 综上: 进行了可行性的方案试探,也完成了整个功能的开发. 且听我细细

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

    需求: vue-cli项目树形控件:一级节点为本地节点,默认展开一级节点,增删改后局部刷新数据. 增加节点,点击确定后局部刷新,渲染新数据. 源码 element组件样式 <el-tree class="treeitems" :data="data" node-key="id" :props="defaultProps" :load="loadNode" lazy :default-expanded-

  • Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)

    这篇博客主要介绍树形控件的两个小小的功能: 下拉菜单 输入过滤框 以CSS样式为主,也会涉及到Vue组件和element组件的使用. 对于没有层级的数据,我们可以使用表格或卡片来展示.要展示或建立层级关系,就一定会用到树形组件了. 使用Vue + Element UI,构建出最基本的树如下图所示: 现在我们就要在这个基础上进行改造,使页面更加符合我们的交互场景. 下拉菜单 将下拉菜单嵌到树节点中,使操作更加简便.紧凑. 效果演示 效果如图: 图示1:悬浮在树节点状态 图示2:点击三个点图标状态

  • JS对select控件option选项的增删改查示例代码

    Javascript 操作select是表单中常见的一种,下面介绍几种常用的JS动态操作select中的各种方法: 复制代码 代码如下: //动态创建select function createSelect() { var mySelect = document.createElement("select"); mySelect.id = "mySelect"; document.body.appendChild(mySelect); } 复制代码 代码如下: //

  • vue通过element树形控件实现树形表格

    目录 实现效果图 安装依赖 自定义树形控件 其他实现 总结 在vue中通过element树形控件来实现树形表格的效果 通过缩进来实现近似树形表格的效果 实现效果图 安装依赖 $ npm install element-plus --save Element官网 自定义树形控件 分析图中控件分布,每个参数都有固定的width,通过width让数值达到对齐的效果 代码主要通过renderContent函数来自定义树形控件 <template> <div class="mytree&

  • Element树形控件整合带图标的下拉菜单(tree+dropdown+input)

    目录 需求说明: 实现步骤: 本文主要讲述:自定义树形控件<el-tree> 需求说明: Element UI 官网提供的树形控件包含基础的.可选择的.自定义节点内容的.带节点过滤的以及可拖拽节点的树形结构 如下: 我想要的效果是支持搜索效果的树,将鼠标悬浮后显示添加修改图标,点击图标后弹出对应页面:并且在每个文件夹前添加自定义图标. 实现效果: 实现步骤: 1.使用插槽(slot) <el-col :span="4" :xs="24"> &

  • 详解如何实现Element树形控件Tree在懒加载模式下的动态更新

    Element提供的Tree树形控件,可以用清晰的层级结构展示信息,还可以展开或折叠.Tree支持两种加载模式:一次性加载全部树节点和懒加载模式.所谓懒加载模式,是指当需要展开父节点时才渲染子节点.懒加载模式的应用场景适合树节点数据量大的情形,在一定程度上可以优化图形用户界面的响应效率以及提升用户体验.但是,懒加载模式对数据动态刷新应用需求的支持不尽如意.树形控件节点一旦展开就缓存在本地,后续不会再继续更新和刷新节点数据.本文将介绍如何实现Element树形控件Tree在懒加载模式下的动态更新.

  • Vue+Element ui实现树形控件右键菜单

    本文实例为大家分享了Vue+Element ui实现树形控件右键菜单的具体代码,供大家参考,具体内容如下 需求 实现树形控件右键菜单功能,有添加文件.删除文件.重命名功能 一.按需引入ELEMENTUI组件 按需引入ELEMENTUI组件 二.实现菜单功能 1.TEMPLATE 代码如下(示例): <!-- 树形组件 -->   <el-tree               :data="data"               @node-contextmenu=&q

  • vue.js element-ui tree树形控件改iview的方法

    element-ui组件的tree树形控件修改源码改为iview组件 实现原理 修改了element-ui源码,把源码里面的tree模块提取出来 然后修改element自带checkbox等组件为iview的checkbox,并且兼容方法 最后修改element样式,改为iview风格,自己也添加了一些样式 新的tree组件可以说是element的逻辑,iview的风格 <template> <div @click.stop="handleClick" v-show=

  • elementUI Tree 树形控件的官方使用文档

    Tree 树形控件---官方文档地址 用清晰的层级结构展示信息,可展开或折叠. 基础用法 基础的树形结构展示. <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree> <script> export default { data() { return { data: [{ label: '一级 1'

  • ElementUI Tree 树形控件的使用并给节点添加图标

    前言: 因为项目需要用Vue做一个管理系统,其中有一个公司部门的管理页面有用到ElementUI 的树形控件,但是结构中没有使用chexkBox选项框,针对这个功能碰到的一些问题做一下总结 一,数据渲染 1)在<el-tree>标签中绑定data属性 2)在vue实例的data中声明list变量 3)从后台获取到的数据是以数组里面嵌套多个对象的结构并赋值给list, 当前的数据是OrgName为当前结构名称, Children作为子分支数组, 子分支中的结构与当前结构一致 4)在页面中展示结构

随机推荐