【vue】解决el-tree或el-table中树形列表懒加载数据改变后不能实时刷新问题以及使用

news/2024/11/23 2:58:55/

文章目录

    • 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的所有的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"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>

http://www.ppmy.cn/news/569325.html

相关文章

如何升级Windows10(Windows7以上)

首先&#xff0c;打开浏览器&#xff0c;搜索下载Windows10 接着&#xff0c;不要点其他&#xff0c;一定要选择官网&#xff0c;看灰色线的特征 选择“立即下载工具” 下载后的样子 打开后&#xff0c;选择接受 选择“立即升级这台电脑” 然后程序下载文件&#xff0c;等待十…

mysql8以上修改密码

前言&#xff1a; mysql8以上和 mysql8以前更新用户的密码是不一样的。一定要记得&#xff01;&#xff01; 本文先更新mysql8以后的版本更新用户密码方式&#xff0c;后续可能更新mysql8以下的版本。mysql8以上 # 进入mysql mysql -u root -p # 切换数据库 use mysql; # mys…

百万级别或以上的数据如何删除

由于索引需要额外的维护成本&#xff0c;因为索引文件是单独存在的文件&#xff0c;所以当我们对数据的增加&#xff0c;修改&#xff0c;删除都会产生额外的对索引文件的操作&#xff0c;这些操作需要消耗额外的I/O&#xff0c;会降低增/改/删的执行效率。所以&#xff0c;在我…

Java编程——给分数划分等级,90分以上是A,80分以上是B,70分以上是C,60分以上是D,60分(不及格)以下是E

将分数划分为5个等级&#xff0c;90分以上是A&#xff0c;80分以上是B&#xff0c;70分以上是C&#xff0c;60分以上是D&#xff0c;60分&#xff08;不及格&#xff09;以下是E 。 import java.util.Random;public class demo3 {public static void main(String[] args) {Ran…

0031:90分以上(C++)

90分以上 描述 期末考试的分数出来了&#xff0c;如果小明同学的分数达到了90分及以上&#xff0c;他就会大喊一声“Yeah”&#xff0c;现在请你编写一个程序&#xff0c;输入小明同学期末考试的分数&#xff0c;如果他的分数大于等于90&#xff0c;输出“Yeah”(不要输出双引号…

com10以上连接报错

问题现象 首先是QT程序&#xff0c;串口用的QSerialPort&#xff0c;连接com17时报这个错&#xff0c;但连接com4,com5这种串口号&#xff0c;就不报错&#xff1a; 非常奇怪&#xff0c;只要是com1…com9都是可以&#xff0c;但在设备管理器改成com10,com11这种两个数字的都…

安装vue3以上的版本

先安装node.js 为的是能够使用npm指令 Node.js 检查node是否安装成功&#xff1a;node -v 顺便检查npm的版本&#xff1a;npm -v 卸载之前的vue版本(3以下&#xff0c;如果没有安装vue可跳过) 执行 npm uninstall -g vue-cli 安装3以上版本的vue npm install -g vue/c…

查询选修课程2门以上且成绩都在80分以上的学生(MSSQL)

目录 题目要求 表结构 表样例 输出样例&#xff1a; 编译代码&#xff1a; 题目要求 查询选修课程数在2门以上&#xff08;含2门&#xff09;且所有选课成绩都在80分以上&#xff08;含80分&#xff09;的学生的姓名、专业名及总学分。 提示&#xff1a;MSSQLServer 评测SQ…