文章目录
- 1.问题描述
- 2.问题解决
- 1.首先在data return中加入一个map来用于存取数据
- 2.在el-tree或树形列表组件加载子级的方法中,用map存下每次被加载的父节点
- 3.封装一个refreshLoadTree方法,每次增删改查操作之后都调用一下,以此达到实时刷新的目的
- 3.重新发现问题
- 3.1问题描述
- 3.2 问题解决
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"borderlazy: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]// 展开次数+1curr.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"borderlazy: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 = 0getAxios(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();// 调用刷新展开的tablethis.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>