Vue2中使用自定義指令實(shí)現(xiàn)el-table虛擬列表的代碼示例
引言
上一篇文章我們講了虛擬列表的實(shí)現(xiàn)原理,以及在vue3中的使用實(shí)例,感興趣的友友們可以查看相關(guān)內(nèi)容 傳送門。然而,在實(shí)際開發(fā)中,我們可能會面臨其他需求,例如在 el-table
中無法使用分頁技術(shù)的情況下展示海量數(shù)據(jù)。這種情況下,頁面可能會出現(xiàn)卡頓,嚴(yán)重時甚至可能引發(fā)瀏覽器崩潰。針對這一問題,我們需要尋找其他的解決方案。
創(chuàng)建virtualTable組件
首先新建一個virtualTable.vue
文件,代碼如下:
<template> <div style="width: 100%"> <el-table v-virtual-list="virtual" width="100%" height="600" :data="tableData.slice(start, over)"> <el-table-column align="center" prop="date" label="日期" :height="virtual.itemHeight" min-width="180"></el-table-column> <el-table-column align="center" prop="name" label="姓名" :height="virtual.itemHeight" min-width="180"></el-table-column> <el-table-column align="center" prop="address" label="地址" :height="virtual.itemHeight" min-width="180"></el-table-column> </el-table> </div> </template> <script> let timeout = null export default { name: 'virtualTable', data() { return { tableData: [], virtual: { itemHeight: 40, // 每一項(xiàng)高度 scrollClass: '.el-table__body-wrapper', // 有滾動條元素 scrollTop: 0, // 滾動條距離頂部距離 tableHeight: 0 // 可視區(qū)高度 } } }, computed: { // 起始下標(biāo) start() { return Math.max(Math.ceil(this.virtual.scrollTop / this.virtual.itemHeight - 5), 0) }, // 結(jié)束下標(biāo) over() { return Math.min( Math.ceil((this.virtual.scrollTop + this.virtual.tableHeight + 1) / this.virtual.itemHeight + 5), this.tableData.length ) }, // 為了保持列表高度完整且滾動條能正常滾 paddingAttr() { let bottom = (this.tableData.length - this.over) * this.virtual.itemHeight let top = this.start * this.virtual.itemHeight return `${top}px 0 ${bottom}px 0` } }, mounted() { this.init() }, methods: { init() { let _arr = [] for (let i = 1; i <= 100000; i++) { _arr.push({ date: '2016-05-02', name: '王小虎' + i, address: `上海市普陀區(qū)金沙江路 ${i} 弄` }) } this.tableData = _arr timeout = setTimeout(() => { const target = document.querySelector(this.virtual.scrollClass) this.virtual.tableHeight = target.clientHeight ?? 0 this.setPaddingAttr(target) }) }, // 更新padding屬性 setPaddingAttr(target) { let _table = target.querySelector('table') _table.style.padding = this.paddingAttr } }, beforeDestroy() { clearTimeout(timeout) } } </script> <style scoped> ::v-deep th, ::v-deep td { height: 40px; line-height: 40px; padding: 0; } </style>
代碼介紹
這邊重點(diǎn)說一下里面的關(guān)鍵代碼,具體原理可以參考我上一篇文章 傳送門
virtual
對象
virtual
對象虛擬列表相關(guān)的屬性,放在一個對象中方便管理,需要傳入到自定義指令中。
timeout = setTimeout(() => {})
為了解決組件初始化時nextTick
中無法獲取到正確的clientHeight
。
this.virtual.tableHeight = target.clientHeight ?? 0
組件初始化時獲取容器的可視區(qū)高度。
this.setPaddingAttr(target)
設(shè)置paddingAttr
方法,重新計算padding
,為了確保虛擬列表的渲染效果正確。
tips
當(dāng)然這里我們可以將其封裝成一個公共的組件,如果有相同的需求直接使用當(dāng)前組件。這里我就不去封裝了,感興趣的友友們可以去嘗試一下。
添加自定義指令
// 虛擬列表自定義指令 Vue.directive('virtual-list', { bind(el, bind, vNode) { const that = vNode.context let virtual = bind.value if (virtual) { let target = el.querySelector(virtual.scrollClass) target.addEventListener('scroll', () => { // 更新滾動條位置 that.virtual.scrollTop = target.scrollTop // 重新計算padding that.setPaddingAttr(target) }) } } })
關(guān)鍵代碼介紹
const taht = vNode.context
獲取當(dāng)前指令所在組件的上下文this
,以便在后續(xù)的代碼中訪問組件的方法和數(shù)據(jù)。
let virtual = bind.value
獲取組件中傳入的值,內(nèi)部包含虛擬列表的相關(guān)信息。
target.addEventListener('scroll', () => {...})
給容器添加滾動監(jiān)聽事件,當(dāng)用戶滾動時觸發(fā)該事件。
that.virtual.scrollTop = target.scrollTop
更新組件中的 virtual.scrollTop
屬性,記錄當(dāng)前滾動條的位置。
that.setPaddingAttr(target)
該方法由當(dāng)前指令所在組件內(nèi)部提供。重新計算padding
,為了確保虛擬列表的渲染效果正確。
最終效果如下:
tips
該自定義指令不僅可以在 el-table
中實(shí)現(xiàn)虛擬列表,還可以在 el-select
等組件中使用。在實(shí)際開發(fā)中,只要了解其原理,就可以有效地應(yīng)用于實(shí)際操作中。
文章小尾巴
以上就是Vue2中使用自定義指令實(shí)現(xiàn)el-table虛擬列表的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于Vue2 el-table虛擬列表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue-router相關(guān)基礎(chǔ)知識及工作原理
這篇文章主要介紹了vue-router相關(guān)基礎(chǔ)知識及單頁面應(yīng)用的工作原理,需要的朋友可以參考下2018-03-03vue+iview 實(shí)現(xiàn)可編輯表格的示例代碼
這篇文章主要介紹了vue+iview 實(shí)現(xiàn)可編輯表格的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無法輸入的問題
這篇文章主要介紹了vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無法輸入的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04html中創(chuàng)建并調(diào)用vue組件的幾種方法匯總
這篇文章主要介紹了html中創(chuàng)建并調(diào)用vue組件的幾種方法匯總,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-11-11關(guān)于Element?table組件滾動條不顯示的踩坑記錄
這篇文章主要介紹了關(guān)于Element?table組件滾動條不顯示的踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08使用自動導(dǎo)入后eslint報錯eslint9的問題及解決方法
本文介紹了使用`pnpm create vue@latest`創(chuàng)建Vue應(yīng)用時,如何配置ESLint和Prettier,包括解決兩者沖突以及自動導(dǎo)入后Eslint報錯的問題,感興趣的朋友一起看看吧2025-03-03vue實(shí)現(xiàn)的請求服務(wù)器端API接口示例
這篇文章主要介紹了vue實(shí)現(xiàn)的請求服務(wù)器端API接口,結(jié)合實(shí)例形式分析了vue針對post、get、patch、put等請求的封裝與調(diào)用相關(guān)操作技巧,需要的朋友可以參考下2019-05-05Vue項(xiàng)目優(yōu)化打包之前端必備加分項(xiàng)
相信現(xiàn)在很多人都是用Vue做過了各種項(xiàng)目,但是項(xiàng)目代碼做完和上線并不代表這結(jié)束,還有上線以后的優(yōu)化也是很重要的一點(diǎn),這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目優(yōu)化打包的相關(guān)資料,需要的朋友可以參考下2021-09-09