
【vue】解决el-tree或el-table中树形列表懒加载数据改变后不能实时刷新问题以及使用
首先从map中取出刚刚架子啊过子级节点的数据,再用this.$set清空对应父节点的数据,实现视图实时刷新,再通过取出的数据重新加载父节点。//封装一个增删改刷新table数据的方法,组件懒加载数据的节点,data return的maps,及被操作节点的父节点。在使用el-table表格懒加载子级数据,懒加载仅会在第一次展开时加载,后续会使用第一次缓存的数据,而不会重新加载。传入的三个参数分别是:
文章目录
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的所有的keymap.values()
获取map的所有的value4.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>
更多推荐
所有评论(0)