Vue2中使用自定義指令實(shí)現(xiàn)el-table虛擬列表的代碼示例
引言
上一篇文章我們講了虛擬列表的實(shí)現(xiàn)原理,以及在vue3中的使用實(shí)例,感興趣的友友們可以查看相關(guān)內(nèi)容 傳送門。然而,在實(shí)際開發(fā)中,我們可能會(huì)面臨其他需求,例如在 el-table 中無法使用分頁技術(shù)的情況下展示海量數(shù)據(jù)。這種情況下,頁面可能會(huì)出現(xiàn)卡頓,嚴(yán)重時(shí)甚至可能引發(fā)瀏覽器崩潰。針對(duì)這一問題,我們需要尋找其他的解決方案。
創(chuàng)建virtualTable組件
首先新建一個(gè)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', // 有滾動(dòng)條元素
scrollTop: 0, // 滾動(dòng)條距離頂部距離
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
)
},
// 為了保持列表高度完整且滾動(dòng)條能正常滾
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對(duì)象
virtual對(duì)象虛擬列表相關(guān)的屬性,放在一個(gè)對(duì)象中方便管理,需要傳入到自定義指令中。
timeout = setTimeout(() => {})
為了解決組件初始化時(shí)nextTick中無法獲取到正確的clientHeight。
this.virtual.tableHeight = target.clientHeight ?? 0
組件初始化時(shí)獲取容器的可視區(qū)高度。
this.setPaddingAttr(target)
設(shè)置paddingAttr方法,重新計(jì)算padding,為了確保虛擬列表的渲染效果正確。
tips
當(dāng)然這里我們可以將其封裝成一個(gè)公共的組件,如果有相同的需求直接使用當(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', () => {
// 更新滾動(dòng)條位置
that.virtual.scrollTop = target.scrollTop
// 重新計(jì)算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', () => {...})
給容器添加滾動(dòng)監(jiān)聽事件,當(dāng)用戶滾動(dòng)時(shí)觸發(fā)該事件。
that.virtual.scrollTop = target.scrollTop
更新組件中的 virtual.scrollTop 屬性,記錄當(dāng)前滾動(dòng)條的位置。
that.setPaddingAttr(target)
該方法由當(dāng)前指令所在組件內(nèi)部提供。重新計(jì)算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虛擬列表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue-router相關(guān)基礎(chǔ)知識(shí)及工作原理
這篇文章主要介紹了vue-router相關(guān)基礎(chǔ)知識(shí)及單頁面應(yīng)用的工作原理,需要的朋友可以參考下2018-03-03
vue+iview 實(shí)現(xiàn)可編輯表格的示例代碼
這篇文章主要介紹了vue+iview 實(shí)現(xiàn)可編輯表格的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無法輸入的問題
這篇文章主要介紹了vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無法輸入的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
html中創(chuàng)建并調(diào)用vue組件的幾種方法匯總
這篇文章主要介紹了html中創(chuàng)建并調(diào)用vue組件的幾種方法匯總,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-11-11
關(guān)于Element?table組件滾動(dòng)條不顯示的踩坑記錄
這篇文章主要介紹了關(guān)于Element?table組件滾動(dòng)條不顯示的踩坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
關(guān)于vue中輸入框的使用場(chǎng)景總結(jié)
這篇文章主要介紹了關(guān)于vue中輸入框的使用場(chǎng)景總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
使用自動(dòng)導(dǎo)入后eslint報(bào)錯(cuò)eslint9的問題及解決方法
本文介紹了使用`pnpm create vue@latest`創(chuàng)建Vue應(yīng)用時(shí),如何配置ESLint和Prettier,包括解決兩者沖突以及自動(dòng)導(dǎo)入后Eslint報(bào)錯(cuò)的問題,感興趣的朋友一起看看吧2025-03-03
vue實(shí)現(xiàn)的請(qǐng)求服務(wù)器端API接口示例
這篇文章主要介紹了vue實(shí)現(xiàn)的請(qǐng)求服務(wù)器端API接口,結(jié)合實(shí)例形式分析了vue針對(duì)post、get、patch、put等請(qǐng)求的封裝與調(diào)用相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
Vue項(xiàng)目?jī)?yōu)化打包之前端必備加分項(xiàng)
相信現(xiàn)在很多人都是用Vue做過了各種項(xiàng)目,但是項(xiàng)目代碼做完和上線并不代表這結(jié)束,還有上線以后的優(yōu)化也是很重要的一點(diǎn),這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目?jī)?yōu)化打包的相關(guān)資料,需要的朋友可以參考下2021-09-09

