针对懒加载的树组件,节点数据发生变化后,只刷新局部数据,拿到最新的节点

思路

 antd tree提供的loadData属性,支持传入一个方法,用于异步加载子节点的数据。当某一节点的数据已经加载之后,收起节点再次展开是不会触发异步加载的方法的,因此节点数据不会刷新。需要我们手动变更一些值才能触发该方法。

首先要明确树组件触发懒加载的前提条件:

1. expandedKeys包含节点key值

2. loadedKeys不包含需要刷新的节点的key值,即此前未曾加载过

3. treeData中不包含该节点的children数据,即children=[]

只有以上三点同时满足,才会触发loadData方法。

方法

A节点下新增子节点后,刷新A节点的子节点需要3步:

注意:A节点的所有子孙节点均需要回到收起状态,否则会多次调用接口加载已展开的节点数据

  • 1. loadedKeys中移除A节点的key值和其子孙节点的key值
  • 2. treeData中将A节点的children赋空
  • 3. expandedKeys中移除A节点下的所有子孙节点的key值

代码:

// 获取当前节点id以及下面所有子孙节点的id 
getNodeAndChildrenIds (data) {
  let temp = [];
  const loop = (data) => {
    data.map(item => {
      temp.push(item.id)
      if (item.children && item.children.length) {
        loop(item.children);
      }
    })
  }

  loop(data);
  return temp;
},
// 更新树组件的数据
updateTreeData(id) {
  const temp = _.cloneDeep(this.treeData);
  let node;
  const loopFn = (data, id) => {
    if (node) {
       return;
    }
    data.some((item) => {
       if (item.id === id) {
         node = _.cloneDeep(item.children);
         item.children = [];
         return true;
       }
       if (item.children && item.children.length) {
         loopFn(item.children, id);
       }
     });
   };
   // 获取A节点的子节点,并把A节点的children移除
   loopFn(temp, id); 
   this.treeData = _.cloneDeep(temp);
   // 获取A节点下面所有子孙节点的id
   const nodeIds = this.getNodeAndChildrenIds(node);
   // loadedKeys中移除A节点的key
   let loadedKeys = _.cloneDeep(this.loadedKeys.filter(item => item !== id));
   // 去掉A下面已加载的子孙节点的key
   loadedKeys = _.cloneDeep(loadedKeys.filter(item => !nodeIds.includes(item)));
   this.loadedKeys = _.cloneDeep(loadedKeys);
   // 去掉A下面已展开的子孙节点id
   this.expandedKeys = _.cloneDeep(this.expandedKeys.filter(item => 
     !nodeIds.includes(item)));
}

 以上是刷新子节点的方法。

当A节点本身发生变更或删除时,则需要刷新A节点的数据,此时同样可以通过上面的方法。但是这里推荐另一种方式,即手动更新数据,不走接口,这种方式更为简单。

代码:

/** 找到对应的节点执行某操作 */
treeAction (node, id, fn) {
  node.some((item,index) => {
    if (item.id === id) {
      fn(node, item, index)
      return true;
    }
    if (item.children && item.children.length) {
      treeAction(item.children, id, fn);
    }
  });
},
// 删除树节点
async deleteTreeNode(data) {
      await api.deleteFn(data.id);
      this.$message.success('删除成功!');

      // 手动删除A节点和其子孙节点
      treeAction(this.treeData, data.id, (node, item, index) => {
        node.splice(index, 1);
      });
},
// 重命名树节点
async editTreeNode(data, form) {
      const params = {
        ...
      };
      await api.editFn(params);
      this.$message.success('重命名成功!');

      // 手动重置A节点名称
      treeAction(this.treeData, data.id, (node, item, index) => {
        item.name = form.name;
      });
},
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐