elementui tree如何重新渲染指定节点及其子节点(懒加载方式)

问题描述

el-tree组件如何更新指点节点的数据和子节点数据,

问题出现的环境背景及自己尝试过哪些方法

clipboard.png

现象入上图

1、左侧树组件,右侧其他组件
2、左侧树采用异步加载,点击左侧的node,右侧会ajax请求数据并渲染,渲染的是点击node下面的文件夹及其他
3、右侧的文件夹双击是进入,对应左侧也要展开,右侧文件夹编辑可以修改文件夹名称,移动文件夹的路径,还有删除文件夹和新建文件夹的功能,需要左侧树结构也对应更新

相关代码,代码比较多,最后面有文字总结

树结构代码

<el-tree class="teamtree"  
    :props="defaultProps"
    :load="loadNodephoto"
    lazy
    v-if="phototreeshow"
    @node-expand="expandHandle"
    ref="phototree"
    node-key="folderId"
    :default-expanded-keys="defaultexpendphoto"
    empty-text="数据为空"
    :expand-on-click-node="false"
    :highlight-current="true"
    @node-click="handleNodeClick">
</el-tree>

展开方法

loadNodephoto(node, resolve) {
  let res1 = [];
  // 此处缓存了resolve方法,想通过这种方式来更新节点数据
  this.tmpResolvephoto = resolve;
  if ("level" in node) {
    if (node.level === 0) {
      return resolve([
        {
          folderId: 0,
          folderName: "全部图片",
          parentFolderId: null,
          path: "0:全部图片",
          leaf: false
        }
      ]);
    }
  }
  // 这个方法是请求ajax把数据返回
  this.getTreeData(node.data.folderId).then(res => {
    resolve(res);
  });
},
 // 右侧进入左侧对应展开
photoExpend(list) {
  let ori = new Set(this.defaultexpendphoto);
  let now = new Set(list);
  let res = new Set([...ori, ...now]);
  res = Array.from(res);  
  this.defaultexpendphoto = [];
  this.defaultexpendphoto = res; 
},
expandHandle(data,node,arg){
  this.photoExpend([data.folderId]) 
},
/** 图片树重新获取节点数据
 * @type:1/2/3 1:当前文件夹/父级/爷爷级
 * @id:文件夹id
 * @idtype:1/2:传入的id是当前/父级
 */
getPhotoNodeData(type, id, idtype) {
  console.log(type, id, idtype)
  let grandId, grandnode, parentnode, parentId, nownode;
  // 爷级都需要传父级id
  if (type == 3 && idtype == 2) {
    parentnode = this.$refs.phototree.getNode(id);
    if (parentnode) {
      grandId = parentnode.data.parentFolderId || 0;
      console.log(grandId)
      grandnode = this.$refs.phototree.getNode(grandId);
      this.loadNodephoto(grandnode, this.tmpResolvephoto);
    }
  } else if (type == 2 && idtype == 2) {
    parentnode = this.$refs.phototree.getNode(id);
    if (parentnode) {
      this.loadNodephoto(parentnode, this.tmpResolvephoto);
    }
  } else if (type == 2 && idtype == 1) {
    // 父级传入自己的id
    nownode = this.$refs.phototree.getNode(id);
   
    if (nownode) {
      parentId = nownode.data.parentFolderId || 0;
      this.photoExpend([parentId])
      parentnode = this.$refs.phototree.getNode(parentId);
      this.loadNodephoto(parentnode, this.tmpResolvephoto);
    }
  } else {
    console.log(type, idtype);
  }
}


你期待的结果是什么?实际看到的错误信息又是什么?

目前想到的是通过缓存resolve方法,然后通过:load对应的事件方法来重新加载数据。这样发现了一个问题:

  1. 在新建/编辑文件夹我需要更新爷级节点子节点的数据
  2. 其他需要更新父级节点子节点数据
  3. 缓存的resolve方法中有个_this5,测试后发现他指向的是最后一次展开的节点,这样会导致我重新获取后的数据更新到了我最后一次展开的节点中问不是我需要的节点

我现在改成了通过V-if每次修改完成之后都重新渲染tree,这样实际上是有问题的,还请各位大佬给个正确的办法 或者demo ,其实实现的功能类似于windows的文件管理器
联系我:498755303@qq.comu

阅读 49.5k
6 个回答

没有分不让邀请

新手上路,请多包涵

大兄弟你最后是怎么解决的,给个答案呗

1.我的做法, 先获取到当前操作的node,
2.通过node 获取到 parent => childNodes
3.然后遍历childNodes 得到一个新的 数组 nodes, 再通过updateKeyChildren更新节点

这里为什么要得到一个新的数组nodes? 因为element框架里面updateKeyChildren方法,是直接先删掉childNodes,然后再赋值新的data,如果我们直接改childNodes,在赋值的时候childNodes就变成[]数组了,所以其实可以先调用remove,全部把节点删掉,然后再append回来...(滑稽)

// element 代码片段
updateChildren(key, data) {
    const node = this.nodesMap[key];
    if (!node) return;
    const childNodes = node.childNodes;
    for (let i = childNodes.length - 1; i >= 0; i--) {
      const child = childNodes[i];
      this.remove(child.data);
    }
    for (let i = 0, j = data.length; i < j; i++) {
      const child = data[i];
      this.append(child, node.data);
    }
  }

拷贝节点

let id = 3 // 当前操作的node的id (key-node)值
let nodes = []
for (let i = 0; i < childNodes.length; i++) {
   // 因为我要执行的是上下2个节点交换位置
  if (copyNodes[i].data.id === id) {
    nodes[i + 1] = childNodes[i].data
    nodes[i] = childNodes[i + 1].data
  } else if (!nodes[i]) {
    nodes.push(childNodes[i].data)
  }
}
// 更新当前操作父节点的子节点
this.$refs.tree.updateKeyChildren(parent.data.id, nodes)
推荐问题
宣传栏