el-table 多表格彈窗嵌套數(shù)據(jù)顯示異常錯亂問題解決方案
1、業(yè)務(wù)背景
使用vue+element開發(fā)報表功能時,需要列表上某列的超鏈接按鈕彈窗展示,在彈窗的el-table列表某列中再次使用超鏈接按鈕點(diǎn)開彈窗,以此類推多表格彈窗嵌套,本文以彈窗兩次為例
最終效果如下示例頁面

2、具體實(shí)現(xiàn)和問題拋出
<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="創(chuàng)建時間" 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="成功數(shù)量" prop="SuccessNum" min-width="22"></el-table-column>
<el-table-column label="失敗數(shù)量" prop="ErrorNum" min-width="22"></el-table-column>
<el-table-column label="狀態(tài)列表" 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>
<!-- 狀態(tài)列表彈窗 -->
<el-dialog
title="狀態(tài)彈窗"
: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="標(biāo)題" 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: [], // 狀態(tài)列表彈窗
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
},
// 導(dǎo)出
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、分析問題
這里有幾個可能的原因和建議來解決這個問題:
①數(shù)據(jù)問題:首先確保你的數(shù)據(jù)源是正確的。檢查你的表格數(shù)據(jù)是否有任何錯誤或遺漏。
②嵌套表格的渲染時機(jī):如果你的嵌套表格(子表格)是在父表格的某一行展開時才渲染的,那么你需要確保子表格的數(shù)據(jù)在正確的時機(jī)進(jìn)行加載。如果數(shù)據(jù)加載過早,可能會導(dǎo)致異常。
③彈窗的v-if與v-show:如果你使用了v-if來控制彈窗的顯示與隱藏,那么每次彈窗打開都會重新渲染彈窗內(nèi)的內(nèi)容。這可能會導(dǎo)致表格的重新初始化,使用v-show可能會避免這個問題。但需要注意的是,v-show只是在視覺上隱藏元素,元素仍然會被渲染。
④表格的key:如前面所說,Vue使用key來追蹤節(jié)點(diǎn)的身份。如果在嵌套表格的場景中,你使用了相同的key,可能會導(dǎo)致身份識別混亂。確保每個表格都有一個獨(dú)特的key。
⑤樣式?jīng)_突:確保沒有其他樣式影響到表格或彈窗的正常顯示。特別是當(dāng)你使用了自定義樣式或與Element UI樣式?jīng)_突的其他UI庫時。
⑥組件版本:確保你使用的Element UI是最新的版本。舊版本可能存在已知的錯誤,而在新版本中可能已經(jīng)被修復(fù)。
4、解決問題
下面我從表格的key角度解決下問題
1)嘗試給每個彈窗的el-table加個key -- 未解決數(shù)據(jù)錯亂的問題
示例代碼如下:
<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 -- 解決數(shù)據(jù)錯亂的問題
示例代碼如下:
<el-table :key="Id" stripe style="width: 100%" v-loading="loading" row-key="Id" height="300" max-height="300"> </el-table>
雖然此種方法解決了我們的問題,但是考慮到每次打開彈窗都會生成隨機(jī)數(shù)存在一定風(fēng)險性,具體分析如下:
隨機(jī)數(shù)改變了每次渲染時的key值,打破了Vue的節(jié)點(diǎn)身份追蹤機(jī)制。
在這種情況下,由于每次渲染都有一個新的隨機(jī)數(shù)作為key,Vue會將該組件視為全新的節(jié)點(diǎn),從而重新渲染。這樣可以避免由于身份追蹤導(dǎo)致的問題,例如在嵌套表格場景中可能出現(xiàn)的報錯。
然而,需要注意的是,使用隨機(jī)數(shù)作為key并不是一個推薦的做法。因?yàn)閗ey的主要作用是幫助Vue高效地識別和追蹤節(jié)點(diǎn)的身份,以便進(jìn)行差異化更新。隨機(jī)數(shù)作為key會破壞這一機(jī)制,可能導(dǎo)致性能下降和潛在的問題。
因此,盡管使用隨機(jī)數(shù)作為key可以解決某些情況下的報錯,但并不是一個優(yōu)雅的解決方案。更好的方式是仔細(xì)排查問題,找到導(dǎo)致報錯的根本原因,并采取相應(yīng)的措施進(jìn)行修復(fù)。如果實(shí)在無法找到其他解決方案,再考慮使用隨機(jī)數(shù)作為臨時方案。但在長期開發(fā)中,仍然建議尋求更合適、更穩(wěn)定的解決方案。
3)嘗試給每個彈窗的el-table加個唯一的key(固定不是隨機(jī)數(shù)) -- 解決數(shù)據(jù)錯亂的問題(推薦)
示例代碼如下:
<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,可以根據(jù)具體情況定義
generateKey (data) {
const uniqueIdentifier = data.map(item => item.Id).join('_')
return `table_${uniqueIdentifier}`
},至此,更合適、更穩(wěn)定的解決方案完成,我們開頭提到的問題得以解決。有更好辦法或者見解的同學(xué)歡迎評論區(qū)留言,互相學(xué)習(xí)。
到此這篇關(guān)于el-table 多表格彈窗嵌套數(shù)據(jù)顯示異常錯亂問題的文章就介紹到這了,更多相關(guān)el-table 多表格彈窗嵌套內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Django migrate不能發(fā)現(xiàn)app.models的表問題
今天小編就為大家分享一篇解決Django migrate不能發(fā)現(xiàn)app.models的表問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
python腳本爬取字體文件的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了利用python腳本爬取字體文件的實(shí)現(xiàn)方法,文中分享了爬取兩個不同網(wǎng)站的示例代碼,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-04-04
Python+PyQt5實(shí)現(xiàn)自動點(diǎn)擊神器
這篇文章主要為大家詳細(xì)介紹了如何利用Python和PyQt5實(shí)現(xiàn)自動點(diǎn)擊神器,旨在解決重復(fù)性的點(diǎn)擊工作,解放雙手,具有及時性和準(zhǔn)確性,需要的可以參考下2024-01-01
Python中的優(yōu)先隊列(priority?queue)和堆(heap)
這篇文章主要介紹了Python中的優(yōu)先隊列(priority?queue)和堆(heap),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
使用scrapy實(shí)現(xiàn)爬網(wǎng)站例子和實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲(蜘蛛)的步驟
本文分二個示例,第一個是個簡單的爬網(wǎng)站的小例子,第二個例子實(shí)現(xiàn)目是從一個網(wǎng)站的列表頁抓取文章列表,然后存入數(shù)據(jù)庫中,數(shù)據(jù)庫包括文章標(biāo)題、鏈接、時間,大家參考使用吧2014-01-01
python實(shí)現(xiàn)手機(jī)通訊錄搜索功能
這篇文章主要介紹了python模仿手機(jī)通訊錄搜索功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-02-02

