el-table 多表格弹窗嵌套数据显示异常错乱问题

1、业务背景

使用vue+element开发报表功能时,需要列表上某列的超链接按钮弹窗展示,在弹窗的el-table列表某列中再次使用超链接按钮点开弹窗,以此类推多表格弹窗嵌套,本文以弹窗两次为例
最终效果如下示例页面
多表格弹窗嵌套示例图

2、具体实现和问题抛出

<template>
    <div class="el_main">
      <el-table
        stripe
        style="width: 100%"
        v-loading="loading"
        row-key="Id"
        :data="list"
      >
        <el-table-column label="ID" prop="Id" min-width="3"> </el-table-column>
        <el-table-column label="类型" prop="Type" min-width="5">
          <template slot-scope="scope">
            {{ formatTaskType(scope.row.Type) }}
          </template>
        </el-table-column>
        <el-table-column label="详情" prop="TaskTitle" min-width="10" show-overflow-tooltip="true"></el-table-column>
        <el-table-column
          label="详情弹窗" 
          min-width="3">
          <template slot-scope="scope">
            <el-button @click="handleClick(scope.row)" type="text">查看</el-button>
          </template>
        </el-table-column>
        <el-table-column label="创建时间" prop="AddTime" min-width="5">
          <template slot-scope="scope" v-if="scope.row.AddTime">
            {{ (scope.row.AddTime * 1000) | formatDate(2) }}
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 详情弹窗 -->
    <el-dialog
      title="详情弹窗"
      :visible.sync="detailInfoDialogVisible"
      append-to-body
      width="50%">
        <el-table
            stripe
            style="width: 100%"
            v-loading="loading"
            row-key="Id"
            height="300" max-height="650"
            :data="detailInfo">
            <el-table-column label="ID" prop="TaskId" min-width="80"></el-table-column>
            <el-table-column label="名称" prop="TaskName" min-width="65"></el-table-column>
            <el-table-column label="成功数量" prop="SuccessNum" min-width="22"></el-table-column>
            <el-table-column label="失败数量" prop="ErrorNum" min-width="22"></el-table-column>
            <el-table-column label="状态列表" min-width="22">
              <template slot-scope="scope">
                <el-button @click="handleStatusListClick(scope.row)" type="text">查看</el-button>
              </template>
            </el-table-column>
            <el-table-column label="队列列表" min-width="30">
              <template slot-scope="scope">
                <el-button @click="handleQueueDataClick(scope.row)" type="text">查看</el-button>
              </template>
            </el-table-column>
          </el-table>
    </el-dialog>
    <!-- 状态列表弹窗 -->
    <el-dialog
      title="状态弹窗"
      :visible.sync="statusListDialogVisible"
      append-to-body
      width="30%">
        <el-table
            stripe
            style="width: 100%"
            v-loading="loading"
            row-key="Id"
            height="300" max-height="300"
            :data="statusListInfo">
            <el-table-column label="ID" prop="Id" min-width="80" show-overflow-tooltip="true"> </el-table-column>
            <el-table-column label="标题" prop="Title" min-width="80" show-overflow-tooltip="true"></el-table-column>
            <el-table-column label="返回信息" prop="Msg" min-width="80" show-overflow-tooltip="true"></el-table-column>
          </el-table>
    </el-dialog>
    <!-- 队列列表弹窗 -->
    <el-dialog
      title="队列弹窗"
      :visible.sync="queueDataDialogVisible"
      append-to-body
      width="30%">
        <el-table
            stripe
            style="width: 100%"
            v-loading="loading"
            row-key="Id"
            height="300" max-height="300"
            :data="queueDataInfo">
            <el-table-column label="ID" prop="Id" min-width="80" show-overflow-tooltip="true"> </el-table-column>
            <el-table-column label="名称" prop="Name" min-width="80" show-overflow-tooltip="true"></el-table-column>
          </el-table>
    </el-dialog>
</template>

<script type="text/ecmascript-6">
import { GetXXXReportList, ExportXXXReportList } from '@/api/reportManage'

const urlQuery = [
  'id|number',
  'type|number',
  'currPage|number',
  'pageSize|number',
]

export default {
  components: {
  },

  data () {
    return {
      id: '',
      type: '',
      collectTime: '',
      loading: false,
      list: [],
      currPage: 1,
      pageSize: 10,
      counts: 0,
      detailInfo: [], // 详情弹窗
      detailInfoDialogVisible: false,
      statusListInfo: [], // 状态列表弹窗
      statusListDialogVisible: false,
      queueDataInfo: [], // 队列列表弹窗
      queueDataDialogVisible: false,
      typeArray: [
        {
          value: 1,
          label: '类型一',
        },
        {
          value: 2,
          label: '分类二',
        },
        {
          value: 3,
          label: '分类三',
        },
        {
          value: 4,
          label: '分类四',
        },
        {
          value: 5,
          label: '分类五',
        },
        {
          value: 6,
          label: '分类六',
        },
      ],
      exportLoading: false,
    }
  },
  created () {
    this._getList(true)
  },
  methods: {
    async _getList (init = false) {
      this.loading = true
      if (init) {
        this.currPage = 1
      }
      let startTime, endTime
      if (this.collectTime) {
        startTime = this.collectTime[0] / 1000
        endTime = this.collectTime[1] / 1000 + 86399
      }
      this._setQuery(urlQuery)
      try {
        const data = await GetXXXReportList({
          Id: this.id || 0,
          StartTime: startTime || 0,
          EndTime: endTime || 0,
          Type: this.type || 0,
          CurrPage: this.currPage,
          PageSize: this.pageSize,
        })
        this.list = data.List
        this.counts = data.Counts 
      } catch (error) {
        this.counts = 0
        this.list = []
      }
      this.loading = false
    },
    search () {
      this._getList(true)
    },
    reset () {
      this.id = ''
      this.type = ''
      this.collectTime = ''
      this.list = []
      this.counts = 0
      this._getList(true)
    },
    pageChange () {
      this._getList()
    },
    pageSizeChange (val) {
      this.pageSize = val
      this._getList(true)
    },
    handleClick (row) {
      if (row.Type === 1) {
        this.detailInfoDialogVisible = true
        this.detailInfo = row.detailInfo 
      } else if (row.Type === 2) {
        this.xxxDialogVisible = true
        this.xxxInfo = row.xxx
      } else if (row.Type === 3) {
        this.xxxDialogVisible = true
        this.xxxInfo = row.xxx
      }
    },
    handleStatusListClick (row) {
      this.statusListDialogVisible = true
      this.statusListInfo = row.StatusList
    },
    handleQueueDataClick (row) {
      this.queueDataDialogVisible = true
      this.queueDataInfo = row.queueData
    },
    // 导出
    async exportData () {
      this.exportLoading = true
      let startTime, endTime
      if (this.collectTime) {
        startTime = this.collectTime[0] / 1000
        endTime = this.collectTime[1] / 1000 + 86399
      }
      try {
        const data = await ExportXXXReportList({
          Id: this.id || 0,
          StartTime: startTime || 0,
          EndTime: endTime || 0,
          Type: this.type || 0,
        })
        var raw = window.atob(data)
        var uInt8Array = new Uint8Array(data.length)
        for (var i = 0; i < raw.length; i++) {
          uInt8Array[i] = raw.charCodeAt(i)
        }
        const url = window.URL.createObjectURL(new Blob([ uInt8Array ], { type: 'application/vnd.ms-excel' }))
        const link = document.createElement('a')
        link.style.display = 'none'
        link.href = url
        link.setAttribute('download', 'xxxx报表.xlsx')
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      } catch (error) {
        this.exportLoading = false
      }
      this.exportLoading = false
    },
  },
}
</script>

<style lang="scss">
</style>

3、分析问题

这里有几个可能的原因和建议来解决这个问题:
①数据问题:首先确保你的数据源是正确的。检查你的表格数据是否有任何错误或遗漏。
②嵌套表格的渲染时机:如果你的嵌套表格(子表格)是在父表格的某一行展开时才渲染的,那么你需要确保子表格的数据在正确的时机进行加载。如果数据加载过早,可能会导致异常。
③弹窗的v-if与v-show:如果你使用了v-if来控制弹窗的显示与隐藏,那么每次弹窗打开都会重新渲染弹窗内的内容。这可能会导致表格的重新初始化,使用v-show可能会避免这个问题。但需要注意的是,v-show只是在视觉上隐藏元素,元素仍然会被渲染。
④表格的key:如前面所说,Vue使用key来追踪节点的身份。如果在嵌套表格的场景中,你使用了相同的key,可能会导致身份识别混乱。确保每个表格都有一个独特的key。
⑤样式冲突:确保没有其他样式影响到表格或弹窗的正常显示。特别是当你使用了自定义样式或与Element UI样式冲突的其他UI库时。
⑥组件版本:确保你使用的Element UI是最新的版本。旧版本可能存在已知的错误,而在新版本中可能已经被修复。

4、解决问题

下面我从表格的key角度解决下问题
1)尝试给每个弹窗的el-table加个key – 未解决数据错乱的问题
示例代码如下:

<el-table
	:key="Id"
	stripe
	style="width: 100%"
	v-loading="loading"
	row-key="Id"
	height="300" max-height="300">
</el-table>

2)尝试给每个弹窗的el-table加个唯一的key – 解决数据错乱的问题
示例代码如下:

<el-table
	:key="Id"
	stripe
	style="width: 100%"
	v-loading="loading"
	row-key="Id"
	height="300" max-height="300">
</el-table>

虽然此种方法解决了我们的问题,但是考虑到每次打开弹窗都会生成随机数存在一定风险性,具体分析如下:

    随机数改变了每次渲染时的key值,打破了Vue的节点身份追踪机制。
    在这种情况下,由于每次渲染都有一个新的随机数作为key,Vue会将该组件视为全新的节点,从而重新渲染。这样可以避免由于身份追踪导致的问题,例如在嵌套表格场景中可能出现的报错。
    然而,需要注意的是,使用随机数作为key并不是一个推荐的做法。因为key的主要作用是帮助Vue高效地识别和追踪节点的身份,以便进行差异化更新。随机数作为key会破坏这一机制,可能导致性能下降和潜在的问题。
    因此,尽管使用随机数作为key可以解决某些情况下的报错,但并不是一个优雅的解决方案。更好的方式是仔细排查问题,找到导致报错的根本原因,并采取相应的措施进行修复。如果实在无法找到其他解决方案,再考虑使用随机数作为临时方案。但在长期开发中,仍然建议寻求更合适、更稳定的解决方案。

3)尝试给每个弹窗的el-table加个唯一的key(固定不是随机数) – 解决数据错乱的问题(推荐)
示例代码如下:

<el-table
	:key="generateKey(scheduledDataDownloadInfo)"
	stripe
	header-row-class-name="bos_table_header"
	style="width: 100%"
	v-loading="loading"
	row-key="Id"
	height="300" max-height="650"
	:data="scheduledDataDownloadInfo">
</el-table>

在methods中添加方法

// 生成唯一的key,可以根据具体情况定义
generateKey (data) {
  const uniqueIdentifier = data.map(item => item.Id).join('_')
  return `table_${uniqueIdentifier}`
},

至此,更合适、更稳定的解决方案完成,我们开头提到的问题得以解决。有更好办法或者见解的同学欢迎评论区留言,互相学习。

若本文有帮助到阅读本文的同学,欢迎点赞、关注、收藏,互相学习交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/128834.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【狂神说Java】Swagger + 任务

✅作者简介&#xff1a;CSDN内容合伙人、信息安全专业在校大学生&#x1f3c6; &#x1f525;系列专栏 &#xff1a;狂神说Java &#x1f4c3;新人博主 &#xff1a;欢迎点赞收藏关注&#xff0c;会回访&#xff01; &#x1f4ac;舞台再大&#xff0c;你不上台&#xff0c;永远…

重庆市5米数字高程(DEM)数据

重庆位于中国西南部、长江上游地区&#xff0c;地跨东经10511~11011、北纬2810~3213之间的青藏高原与长江中下游平原的过渡地带。东邻湖北、湖南&#xff0c;南靠贵州&#xff0c;西接四川&#xff0c;北连陕西&#xff1b;辖区东西长470千米&#xff0c;南北宽450千米&#xf…

uni-app——項目day01

配置uni-app開發環境 uni-app快速上手 | uni-app官网 创建项目 图中四个划线就是要配置的地方. 选择vue2还是vue3看个人选择。 目录结构 但是现在新版本创建的项目已经没有components目录了&#xff0c;需要自己创建。 项目运行到微信开发者工具 使用git管理项目 node-mod…

【神印王座】林鑫和李馨甜蜜接吻,团灭七阶恶魔,温馨结尾

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料&#xff0c;《神印王座》80话最新剧情解析。有关李馨与林鑫的爱情故事源于一场争执。那时&#xff0c;两人都年轻气盛&#xff0c;不肯向对方低头。但是&#xff0c;经过一段时间的相处&#xff0c;…

ARM day4

LED灯亮灭控制 .text .global _start _start: 1ldr r0,0x50000a28ldr r1,[r0]orr r1,r1,#(0x3<<4)str r1,[r0] 2ldr r0,0x50006000ldr r1,[r0]bic r1,r1,#(0x3<<20)orr r1,r1,#(0x1<<20)bic r1,r1,#(0x3<<16)orr r1,r1,#(0x1<<16)str r1,[r0]…

java语法:继承与多态

导言: 在Java中&#xff0c;继承和多态是面向对象编程的两个重要概念&#xff0c;它们允许我们创建更加灵活和可扩展的代码。本文主要对继承和多态的语法和一些细节做一个介绍和解释。 目录 导言: 正文&#xff1a; 一.继承 1. 基本语法 2. 继承的特点 3.子类中访问父类…

补坑:Java的字符串String类(1)

常用方法 字符串构造 来看看源码里面String的构造方法 普通字符串 //"hello" 是字符串常量&#xff0c;没有\0标记结尾String str "hello";System.out.println(str);//helloString str2 new String();System.out.println(str2);//没有输出String str3…

“三位一体”超级混沌工程主要特点及功能

“三位一体”超级混沌工程X-Chaos主要包括基础故障编排、业务场景故障编排、演练场景编排、故障库管理、演练场景管理、演练计划管理、演练观测和演练报告等模块&#xff0c;支持对传统架构、云环境以及国产化基础环境的IT系统进行故障演练。本文将介绍混沌工程主要特点及主要功…

归并分治 笔记

归并分治 前置知识&#xff1a;讲解021-归并排序 原理&#xff1a; (1&#xff09;思考一个问题在大范围上的答案&#xff0c;是否等于&#xff0c;左部分的答案 右部分的答案 跨越左右产生的答案(2&#xff09;计算“跨越左右产生的答案”时&#xff0c;如果加上左、右各自…

GeoGebra:数学动画制作工具重磅来袭

【线性代数】线性代数可视化工具&#xff1a;manim manim是之前我跟大家分享的一个线性代数动画制作工具。 但我之前的描述有些许偏差&#xff0c;这里要更正一下&#xff0c;manim不仅限于制作线性代数动画&#xff0c;也可以制作数学其他学科的动画&#xff0c;例如微积分&…

Selenium是什么,带你了解自动化测试的神奇之处

一、使用测试工具 工欲善其事&#xff0c;必先利其器。在开始具体的自动化测试之前&#xff0c;我们需要做好更多的准备&#xff0c;包括以下几个方面&#xff1a; 认识自动化测试 准备自动化测试工具 使用有效的方式 针对具体的测试对象 接下来的第一部分内容&#xff0c;我…

JavaScript如何实现钟表效果,时分秒针指向当前时间,并显示当前年月日,及2024春节倒计时,源码奉上

本篇有运用jQuery&#xff0c;记得引入jQuery库&#xff0c;否则不会执行的喔~ <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <meta name"chenc" content"Runoob"> <met…

人工智能中的基础之一——Python

Python作为一种简洁、易学、功能丰富的高级编程语言&#xff0c;被广泛应用于数据分析、人工智能、Web开发等各个领域。本文将介绍Python的基础语法和使用&#xff0c;帮助读者快速上手Python编程。 一、Python基础语法 1. 变量和数据类型 在Python中&#xff0c;可以使用变…

C#,Python实践,用CodeFormer实现人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色

无论是自己、家人或是朋友、客户的照片&#xff0c;免不了有些是黑白的、被污损的、模糊的&#xff0c;总想着修复一下。作为一个程序员 或者 程序员的家属&#xff0c;当然都有责任满足他们的需求、实现他们的想法。除了这个&#xff0c;学习了本文的成果&#xff0c;或许你还…

【Unity程序小技巧】如何消除多次Destory带来的性能消耗

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Linux学习第36天:Linux RTC 驱动实验:时间是一条流淌的河

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 RTC就是实时时钟。 本笔记主要学习Linux RTC驱动试验&#xff0c;主要内容包括Linux内核RTC驱动简介、I.MX6U内部RTC分析、RTC时间查看与设置。因为Linux内核已经…

Docker - 常用命令

Docker - 常用命令 帮助命令 docker version # 查看docker版本信息 docker info # 显示docker的系统信息&#xff0c;包括镜像和容器的数量 docker 命令 --help # 帮助命令官网帮助文档&#xff1a;https://docs.docker.com/engine/reference/commandline/cli/ 镜像…

接口测试及常用接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

【算法与数据结构】77、LeetCode组合

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;如果k是固定的&#xff0c;最直接的方法就是建立k个for循环&#xff0c;将结果全部压入result容器中。…

联合阿里在职测开工程师耗时一个星期写的 【接口测试+自动化接口接口测试详解]

1&#xff1a;json模块的使用  2&#xff1a;接口自动化测试概叙 3&#xff1a;swagger工具能导出接口文档的 4:前端页面: 5:后端: 6:前端和后端的数据交互&#xff08;接口&#xff09;通过接口 7&#xff1a;接口的概念 8&#xff1a;常用的接口方式&#xff08;协议…