1.问题描述

在项目中遇到一个关于el-table的树型结构修改数据后不刷新的问题,需要手动刷新之后才能刷新

2.问题解决

1.首先在data return中加入一个map来用于存取数据

data() {
    return {
      maps: new Map()
    }
  }

知识补充:
Map对象:
1.Map是用来寸键值对的数据,它与Object不同在于:

  • Object中的属性名只能是字符串或符号,如果传递了一个其他类型的属性名,JS解释器会自动将其转换为字符串
  • Map中任何类型的值都可以成为数据的key
  • 2.创建Map对象
    const map = new Map()
    
    map.set("key", "value")
    
    
    map.delete(key)
    
    console.log(map.get("key"))   //value
    console.log(map.has("key"))  //ture or false
    

    3.常用方法介绍

  • map.size() 获取map中键值对的数量
  • map.set(key, value) 向map中添加键值对
  • map.get(key) 根据key获取值
  • map.delete(key) 删除指定数据
  • map.has(key) 检查map中是否包含指定键
  • map.clear() 删除全部的键值对
  • map.keys() 获取map的所有的key
  • map.values() 获取map的所有的value
  • 4.Map转数组

    // 方法一:
    const arr = Array.from(map) // [["name","孙悟空"],["age",18]]
    // 方法二:
    const arr = [...map]
    

    参考借鉴于:Map对象及常用方法介绍

    2.在el-tree或树形列表组件加载子级的方法中,用map存下每次被加载的父节点

    async loadChildren(tree,treeNode,rsolve){
    	this.maps.set(tree.id,{tree,treeNode,resolve}) //储存数据
    	// 调用接口,回显树型内容
    	const resp =  await this.getChildren(tree.id)
    	resolve(resp.data)
    }
    

    3.封装一个refreshLoadTree方法,每次增删改查操作之后都调用一下,以此达到实时刷新的目的

    refreshLoadTree(lazyTreeNodeMap, maps, parentId) {
          if (maps.get(parentId)) {
            const { tree, treeNode, resolve } = maps.get(parentId)
            this.$set(lazyTreeNodeMap, parentId, [])
            if (tree) { // 重新执行父节点加载子级操作
              this.loadChildren(tree, treeNode, resolve)
              if (tree.parentId) { // 若存在爷爷结点,则执行爷爷节点加载子级操作,防止最后一个子节点被删除后父节点不显示删除按钮
                const a = maps.get(tree.parentId)
                this.loadChildren(a.tree, a.treeNode, a.resolve)
              }
            }
          }
        }
    

    传入的三个参数分别是:组件懒加载数据的节点,存储的maps数据,被操作节点的父节点

    使用

    this.refreshLoadTree(this.$refs.table.store.states.lazyTreeNodeMap, this.maps, this.temp.parentId)
    

    组件

    <el-table ref="table"></el-table>
    

    原理

    首先从map中取出刚刚架子啊过子级节点的数据,再用this.$set清空对应父节点的数据,实现视图实时刷新,再通过取出的数据重新加载父节点

    以上内容参考:解决el-tree或树形列表懒加载数据改变后不能实时刷新问题

    3.重新发现问题

    3.1问题描述

    在使用el-table表格懒加载子级数据,懒加载仅会在第一次展开时加载,后续会使用第一次缓存的数据,而不会重新加载。

    3.2 问题解决

     <el-table
        :data="tableData1"
        style="width: 100%"
        row-key="id"
        border
        lazy
        :load="load"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
        @expand-change="hanleExpandChange">
        <!--   内容省略   -->
    </el-table>
    

    字段描述

    row-key:渲染树型结构数据的时候为必填
    lazy :属性为true的时候加载函数load
    @expand-change : 当用户对某一行展开或者关闭的时候会触发该事件,(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded)

    1.load方法中的内容

    async load(tree,treeNode,resolve){
    	// 在声明的全局变量中,增加一个key为本条数据的id,id可替换为数据中的任意值
    	this.tableTreeRefreshTool[tree.id] = {}
        // 重要!保存resolve方法,以便后续使用
        this.tableTreeRefreshTool[tree.id].resolve = resolve
        // 记录展开次数,具体作用后续介绍
        this.tableTreeRefreshTool[tree.id].expandCount = 0
    	// 调用接口
    	const resp =  await this.getChildren(tree.id)
    	resolve(resp.data)
    }
    

    2.设置expand-change事件

    async hanleExpandChange(row,expanded){
    	// 获取到之前保存的全局变量
    	const curr = this.tableTreeRefreshTool[row.id]
    	// 展开次数+1
    	curr.expandCount++
    	// 如果是展开状态,且展开次数大于1,且上一次的状态为折叠,则请求api数据更新子菜单
    	 if (expanded && curr.expandCount > 1 && !curr.prevStatus) {
            // api请求
            const resp =  await this.getChildren(tree.id)
    		curr.resolve(resp.data)
          
        }
        // 保存本次的展开或折叠状态,用于下次判断
        curr.prevStatus = expanded
    
    }
    

    数据解释

    expandCount 代表展开次数,这是为了防止第一次展开时,已经被lozyload加载过了,这里再次重复加载导致冲突
    使用prevStatus是因为调用resolve方法后,会再次触发这个expand-change方法,如果不进行判断,会导致死循环

    以上内容参考:ElementUI el-table树形表格懒加载如何手动刷新 el-table树状表格手动刷新的方法

    至此,有关于load的bug修改完成,完整代码如下

    <template>
    	 <el-table
    	    :data="tableData1"
    	    style="width: 100%"
    	    row-key="id"
    	    border
    	    lazy
    	    :load="load"
    	    :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
    	    @expand-change="hanleExpandChange">
    	    <!--   内容省略   -->
    	</el-table>
    </template>
    <script>
    export default {
    	data(){
    		return {
    			 mapstableTree: new Map(),
         		 tableTreeRefreshTool: {},
    		}
    	},
    	methods:{
    		load(tree, treeNode, resolve){
    	 	 //增删改的时候存储数据
    	      this.mapstableTree.set(tree.id, { tree, treeNode, resolve })
    	      // 在之前声明的全局变量中,增加一个key为 本条数据的id,id可替换为你数据中的任意唯一值
    	      this.tableTreeRefreshTool[tree.id] = {}
    	      //  重要!保存resolve方法,以便后续使用
    	      this.tableTreeRefreshTool[tree.id].resolve = resolve
    	      //  记录展开次数,具体作用后续介绍
    	      this.tableTreeRefreshTool[tree.id].expandCount = 0
    	
    	
    	
    	      getAxios(tree.id).then(res => {
    	        resolve(res.data.erpOrderProductList)
    	      })
    		},
    		 //封装一个增删改刷新table数据的方法,组件懒加载数据的节点,data return的maps,及被操作节点的父节点
    	    refreshLoadTree (lazyTreeNodeMap, maps, parentId) {
    	      console.log("单个刷新的tree", lazyTreeNodeMap, maps, parentId);
    	      if (maps.get(parentId)) {
    	        const { tree, treeNode, resolve } = maps.get(parentId)
    	        this.$set(lazyTreeNodeMap, parentId, [])
    	        if (tree) { // 重新执行父节点加载子级操作
    	          this.loadTreeChild(tree, treeNode, resolve)
    	          if (tree.parentId) { // 若存在爷爷结点,则执行爷爷节点加载子级操作,防止最后一个子节点被删除后父节点不显示删除按钮
    	            const a = maps.get(tree.parentId)
    	            this.loadTreeChild(a.tree, a.treeNode, a.resolve)
    	          }
    	        }
    	      }
    	    },
    	     handleExpandChange (row, expanded) {
    
    	      const curr = this.tableTreeRefreshTool[row.id]
    	
    	      // this.refreshLoadTree(this.$refs.table.store.states.lazyTreeNodeMap, this.mapstableTree, this.form.productId)
    	      curr.expandCount++
    	      // 如果是展开状态,且展开次数大于1,且上一次的状态为折叠,则请求api数据,更新子菜单
    	      if (expanded && curr.expandCount > 1 && !curr.prevStatus) {
    	     
    	        getAxios(row.id).then(res => {
    	          curr.resolve(res.data.shopProductVariantList)
    	        })
    	      }
    	      // 保存本次的展开或折叠状态,用于下次判断
    	      curr.prevStatus = expanded
    	    },
    		// 提交修改按钮
    		submitForm(){
    			 this.$refs["form"].validate(valid => {
            if (valid) {
              this.$refs['tableform'].validate(table => {
                if (table) {
                  if (this.form.id != null) {
                    updateErpOrder(this.form).then(response => {
                      this.$modal.msgSuccess("修改成功");
                      this.open = false;
                      this.getList();
                      // 调用刷新展开的table
                      this.refreshLoadTree(this.$refs.table.store.states.lazyTreeNodeMap, this.mapstableTree, this.form.id)
                    });
                  } else {
                    addErpOrder(this.form).then(response => {
                      this.$modal.msgSuccess("新增成功");
                      this.open = false;
                      this.getList();
                    });
                  }
                }
              })
    
    
            }
          });
    		}
    	}
    	
    }
    </script>
    
    
Logo

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

更多推荐