el-tree懒加载回显数据

前几天一个月薪35k的兄弟,给我推了一个人工智能学习网站,看了一段时间挺有意思的。包括语音识别、机器翻译等从基础到实战都有,很详细,分享给大家。大家及时保存,说不定啥时候就没了。

描述
懒加载回显,需要两个数据

1、你展开的节点key数组
2、你勾选的节点key数组

- key可以是id,这个在el-tree绑定

- 将这两个数据在保存的时候传给后端

- 点击编辑时,让后端返回对应的这两个数据

- 通过default-checked-keys回显勾选

- 通过default-expanded-keys回显展开过的节点

效果

在这里插入图片描述

dom
<el-tree
  ref="tree"
  :data="treeData"
  :load="loadnode"
  :lazy="isLazy"
  check-on-click-node
  check-strictly
  :props="defaultProps"
  show-checkbox
  node-key="nodeId"
  @node-expand="keepExpandedNode"
  @check-change="hChangeTree" 
  @check="handleCheckChange"
  :default-expanded-keys="defaultExpandedNodes"
  :default-checked-keys="defaultCheckedNodes"
></el-tree>
保存展开过的节点数组,保存选中的节点数组
//保存展开过的节点
    keepExpandedNode(nodeData, node, tree) {
        let newFlag = this.expandedNodes.every(item => {
            return item.nodeId !== nodeData.nodeId
        });
        if (newFlag && !nodeData.isLeaf) {
            this.expandedNodes.push(this.cloneObj(nodeData))
        }
    },
    //点击多选框->整理已选选项并保存
    handleCheckChange(node, tree) {
      let list = this.cloneObj(tree.checkedNodes);  //tree.checkedNodes-未展开过的节点的子节点无法获取到
      list = list.filter(mItem => {
          return this.expandedNodes.every(item => {
              return item.nodeId !== mItem.nodeId
          })
      });
      this.value = list;
    },
    //深度复制对象
    cloneObj(obj) {
        let newObj = {};
        if (typeof obj === "object") {
            if (obj instanceof Array) {
                newObj = [];
            }
            for (var key in obj) {
                let val = obj[key];
                newObj[key] =
                    typeof val === "object" ? this.cloneObj(val) : val;
            }
            return newObj;
        } else {
            return obj;
        }
    },
data
data() {
   return {
     expandedNodes: [],  // 已经展开过的节点(拿到过下级的节点)
     value: [], // 已选节点
     defaultCheckedNodes: [], // 最终要回显的勾选key数组
     defaultExpandedNodes: [], // 最终要回显的展开过的key数组
     openList: [], // 后端返回的展开节点数据(需要处理成key数组)
     choliceList: [], // 后端返回的勾选节点数据(需要处理成key数组)
     meaningExpandedNum: 0, // 标的
   }
}
watch里监听

(非必需,我这里是因为后端返回数据结构问题,所以需要转化)

expandArr: {
      handler(newV, oldV) {
        if(newV){
          this.$nextTick(() => {
            this.openList = newV.split(',')
            // console.log(this.openList);
          })
          // console.log(this.defaultExpandedNodes);
        }
      },
      immediate: true,
    }, 
    selectArr: {
      handler(newV, oldV) {
        if(newV){
          this.$nextTick(() => {
            this.choliceList = newV.split(',')
          })
          // console.log(this.defaultCheckedNodes);
        }
      },
      immediate: true,
    }, 
回显
   async gettreeData(i, p, search) {  // 获取tree数据
      const res = await getTreeData({
        level: i,
        parentId: p,
      });
      if(i == 1){
        this.firstTreeData = res.data.content
      }
      return res.data.content;
    },
    
    async loadnode(node, resolve) {  // tree懒加载
      if (node.level == 0) {
        /// 如果需要多次回填,该初始化必需
        this.meaningExpandedNum = 0;
        this.defaultCheckedNodes = [];

        /// 回填展开节点
        this.$nextTick(()=>{
          this.defaultExpandedNodes = this.openList
        })

        setTimeout(async() => {
          let list = await this.gettreeData(1, "root");
          resolve(list);

          /// 注意回填要在树渲染后才生效
            this.$nextTick(() => {
            /// 没展开过节点,则直接在根节点层级回填
                if (0 === this.defaultExpandedNodes.length) {
                    this.defaultCheckedNodes = this.choliceList.map(item => {
                        return item
                    });
                }
            });
        },500)
      } else {
        let search = this.searchVal;
        this.gettreeData(node.level + 1, node.data.nodeId,).then(
          (res) => {
            if (res) {
              setTimeout(() => {
                resolve(res);

                /// 已选节点变成展开节点时、选值自动替换为下层节点;这是为了下次回填做的准备,回填过程中用不到
                if(node.checked){
                  let list = this.$refs.tree.getCheckedNodes();
                  list = list.filter(mItem => {
                      return this.expandedNodes.every(item => {
                          return item.nodeId !== mItem.nodeId
                      })
                  })
                  this.value = list;
                }

                /// 回填时保证在全部渲染后再回填
                this.meaningExpandedNum++;

                if (this.meaningExpandedNum === this.defaultExpandedNodes.length) {
                /// 回填复选框
                    this.defaultCheckedNodes = this.choliceList
                }
              }, 200);
            } else {
              return resolve([]);
            }
          }
        );
        
      }
    },
    
保存时将展开过的节点和勾选过的节点传给后端

我这里是因为组件封装有些多,所以需要将数据保存到vuex,最后再传给后端。

async hChangeTree(node) {
      let cholice = this.$refs.tree.getCheckedNodes()
      let choliceArr = [];
      cholice.forEach((item)=>{
        choliceArr.push(item.entityId)
      })
      // console.log(choliceArr);
      this.$store.commit("uploadCholiceNodeG",choliceArr)
      // 保存展开tree节点和勾选tree节点数据
}
遇到问题

懒加载回显,获取节点时,同时调用好几个接口,造成先padding,后500的bug,修复如下:

请求时参数正常,先padding,后500bug

参考

elementUI-Tree-懒加载树的选中与回填

Logo

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

更多推荐