vue3+element-plus實(shí)現(xiàn)兩個(gè)表格同步滾動(dòng)功能
需求:現(xiàn)在需要兩個(gè)表格,為了方便對(duì)比左右的數(shù)據(jù),需要其中一邊的表格滾動(dòng)時(shí),另一邊的表格也跟著一起滾動(dòng),并且保持滾動(dòng)位置的一致性。具體如下圖所示。

實(shí)現(xiàn)步驟:
確保兩個(gè)表格的寬度一致:如果兩個(gè)表格的寬度不一致,可能會(huì)導(dǎo)致滾動(dòng)條的位置不同步。確保兩個(gè)表格的寬度相同(數(shù)據(jù)內(nèi)容超出表格行的寬度可以省略顯示)或根據(jù)需要調(diào)整。
使用相同的滾動(dòng)容器:確保兩個(gè)表格的滾動(dòng)容器具有相同的高度,這樣它們的滾動(dòng)行為才會(huì)同步。
同步滾動(dòng)事件:在兩個(gè)表格上監(jiān)聽(tīng)滾動(dòng)事件,并在事件觸發(fā)時(shí)同步另一個(gè)表格的滾動(dòng)位置。
HTML結(jié)構(gòu):
創(chuàng)建一個(gè)包含兩個(gè)表格的容器,然后給容器一個(gè)固定的高度(因?yàn)橐獙?shí)現(xiàn)滾動(dòng)必須要內(nèi)容超過(guò)高度了才會(huì)滾動(dòng))。
<template>
<div class="container-box">
<div class="flex table-box">
<!-- 左邊表格 -->
<div class="left-table" ref="leftTableWrapper">
<el-table
:data="LeftTableData"
border
ref="leftTableRef"
style="width: 100%"
height="100%"
:fit="true"
header-row-class-name="header-row"
:cell-style="{
'font-size': '12px',
color: '#666666',
height: '40px',
}"
>
<template #empty>
<div class="custom-empty">
<el-empty
:image="`${$global.imageBaseUrl}/ledger/billProcessing/icon_nodata.png`"
description="暫無(wú)數(shù)據(jù)"
/>
</div>
</template>
<el-table-column
label="表頭1"
prop="left1"
align="center"
min-width="150"
/>
<el-table-column
label="表頭2"
prop="left2"
align="center"
width="100"
/>
</el-table>
</div>
<!-- 右邊表格 -->
<div class="right-table" ref="rightTableWrapper">
<el-table
:data="rightTableData"
border
ref="rightTableRef"
style="width: 100%"
height="100%"
:fit="true"
header-row-class-name="header-row"
:cell-style="{
'font-size': '12px',
color: '#666666',
height: '40px',
}"
>
<template #empty>
<div class="custom-empty">
<el-empty
:image="`${$global.imageBaseUrl}/ledger/billProcessing/icon_nodata.png`"
description="暫無(wú)數(shù)據(jù)"
/>
</div>
</template>
<el-table-column
label="表頭1"
prop="right1"
align="center"
min-width="150"
/>
<el-table-column
label="表頭2"
prop="right2"
align="center"
width="100"
/>
</el-table>
</div>
</div>
</div>
</template>JavaScript邏輯:
模擬左右表格的數(shù)據(jù),初始設(shè)置100條。
在兩個(gè)表格上監(jiān)聽(tīng)滾動(dòng)事件,并在事件觸發(fā)時(shí)同步另一個(gè)表格的滾動(dòng)位置。
使用
nextTick確保DOM更新完成后再同步滾動(dòng)位置。setupTableScrollSync 函數(shù)通過(guò)獲取 el-table 的 body 容器,給左右表格的滾動(dòng)事件綁定同步邏輯,避免循環(huán)觸發(fā)(用 isSyncingScroll 標(biāo)記)。
<script lang="ts" setup>
interface tableInfo {
left1?: string
left2?: string
right1?: string
right2?: string
}
let LeftTableData = ref<tableInfo[]>([])
let rightTableData = ref<tableInfo[]>([])
const leftTableRef = ref()
const rightTableRef = ref()
const leftTableWrapper = ref()
const rightTableWrapper = ref()
onMounted(() => {
for (let index = 0; index < 100; index++) {
let obj = {
left1: `表${index + 1}`,
left2: `表${index + 1}-1`,
}
let obj2 = {
right1: `表${index + 1}`,
right2: `表${index + 1}-1`,
}
LeftTableData.value.push(obj)
rightTableData.value.push(obj2)
}
// 表格滾動(dòng)同步
nextTick(() => {
setupTableScrollSync()
})
})
// 滾動(dòng)同步實(shí)現(xiàn)
let isSyncingScroll = false
function setupTableScrollSync() {
// 獲取表格body的滾動(dòng)容器
const getTableBodyWrapper = (tableRef: any) => {
// el-table exposes $el, then .querySelector('.el-scrollbar__wrap')
// 兼容 el-table 2.x/3.x
if (!tableRef?.value) return null
// 先找新版class
let body = tableRef.value.$el.querySelector('.el-scrollbar__wrap')
if (!body) {
// 舊版class
body = tableRef.value.$el.querySelector('.el-table__body-wrapper')
}
return body
}
const leftBody = getTableBodyWrapper(leftTableRef)
const rightBody = getTableBodyWrapper(rightTableRef)
if (!leftBody || !rightBody) return
// 解綁舊的監(jiān)聽(tīng),防止重復(fù)
leftBody.onscroll = null
rightBody.onscroll = null
leftBody.onscroll = (e: Event) => {
if (isSyncingScroll) return
isSyncingScroll = true
rightBody.scrollTop = leftBody.scrollTop
isSyncingScroll = false
}
rightBody.onscroll = (e: Event) => {
if (isSyncingScroll) return
isSyncingScroll = true
leftBody.scrollTop = rightBody.scrollTop
isSyncingScroll = false
}
}
</script>CSS 樣式:
<style lang="scss" scoped>
.container-box {
background-color: #fff;
border-radius: 4px;
margin: 16px;
height: calc(100vh - 100px);
padding: 24px;
.table-box {
height: calc(100% - 465px);
.left-table {
margin-right: 16px;
}
.left-table,
.right-table {
:deep(.header-row th) {
background-color: #f5f5f5;
text-align: center;
}
}
}
}
</style>想要實(shí)現(xiàn)表格同步滾動(dòng),其實(shí)還有一個(gè)辦法,就是用一個(gè)表格來(lái)實(shí)現(xiàn)(前提是數(shù)據(jù)是放在一個(gè)數(shù)組里的) ,然后中間想要空隙,通過(guò)CSS樣式為表格的某些行或列添加間隔,這種方法實(shí)現(xiàn)簡(jiǎn)單,無(wú)需處理滾動(dòng)邏輯。如果需要真正的固定列+滾動(dòng)列效果,推薦用兩個(gè)表格來(lái)實(shí)現(xiàn);如果只是視覺(jué)分隔,一個(gè)表格來(lái)實(shí)現(xiàn)更簡(jiǎn)單。
到此這篇關(guān)于vue3+element-plus,實(shí)現(xiàn)兩個(gè)表格同步滾動(dòng)的文章就介紹到這了,更多相關(guān)vue3 element-plus表格同步滾動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue3中element-plus表格搜索過(guò)濾數(shù)據(jù)
- Vue3中的element-plus表格實(shí)現(xiàn)代碼
- element-plus+Vue3實(shí)現(xiàn)表格數(shù)據(jù)動(dòng)態(tài)渲染
- vue3?element-plus?實(shí)現(xiàn)表格數(shù)據(jù)更改功能詳細(xì)步驟
- Vue3集成Element-plus快速搭建頁(yè)面框架的過(guò)程
- VUE3+Element-plus中el-form的使用示例代碼
- vue-treeselect(適配Vue3.2)及Element-plus的TreeSelect組件使用
- vue3 element-plus如何使用icon圖標(biāo)組件
相關(guān)文章
Vue3中使用Element?Plus時(shí)el-icon無(wú)法顯示的問(wèn)題解決
我們的Vue前端一般都是用的ElementUI,其中按鈕可能用到的比較多,官方里面有自帶的一些默認(rèn)圖標(biāo),下面這篇文章主要給大家介紹了關(guān)于Vue3中使用Element?Plus時(shí)el-icon無(wú)法顯示的問(wèn)題解決,需要的朋友可以參考下2022-03-03
vue項(xiàng)目展示pdf文件的方法實(shí)現(xiàn)
本文主要介紹了vue項(xiàng)目展示pdf文件的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Vue.js實(shí)戰(zhàn)之使用Vuex + axios發(fā)送請(qǐng)求詳解
這篇文章主要給大家介紹了關(guān)于Vue.js使用Vuex與axios發(fā)送請(qǐng)求的相關(guān)資料,文中介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-04-04
Vue3?中的?readonly?特性及函數(shù)使用詳解
readonly是Vue3中提供的一個(gè)新特性,用于將一個(gè)響應(yīng)式對(duì)象變成只讀對(duì)象,這篇文章主要介紹了Vue3?中的?readonly?特性詳解,需要的朋友可以參考下2023-04-04
Vue?+?SpringBoot?實(shí)現(xiàn)文件的斷點(diǎn)上傳、秒傳存儲(chǔ)到Minio的操作方法
這篇文章主要介紹了Vue?+?SpringBoot?實(shí)現(xiàn)文件的斷點(diǎn)上傳、秒傳存儲(chǔ)到Minio的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-06-06

