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