如何为Vuetify的v-data-table添加顶部和底部水平滚动条
给Vuetify v-data-table添加顶部+底部双水平滚动条
方案:JS同步滚动容器(可靠兼容)
这个方法通过创建与表格底部滚动容器同步的顶部滚动条,实现双向滚动同步,同时支持窗口大小变化自适应。
修改后的完整代码:
<template> <v-container> <!-- 顶部滚动容器 --> <div ref="topScrollWrapper" class="top-scroll-wrapper"></div> <v-data-table ref="tableRef" :headers="headers" :items="desserts" :items-per-page="5" class="elevation-1" ></v-data-table> </v-container> </template> <script> export default { name: 'HelloWorld', data () { return { headers: [ { text: 'Dessert (100g serving)', align: 'start', sortable: false, value: 'name', width: 300 }, { text: 'Calories', value: 'calories', width: 300}, { text: 'Fat (g)', value: 'fat', width: 300 }, { text: 'Carbs (g)', value: 'carbs', width: 300 }, { text: 'Protein (g)', value: 'protein', width: 300 }, { text: 'Iron (%)', value: 'iron', width: 300 }, ], desserts: [ { name: 'Frozen Yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, iron: '1%', }, { name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, iron: '1%', }, { name: 'Eclair', calories: 262, fat: 16.0, carbs: 23, protein: 6.0, iron: '7%', }, { name: 'Cupcake', calories: 305, fat: 3.7, carbs: 67, protein: 4.3, iron: '8%', }, { name: 'Gingerbread', calories: 356, fat: 16.0, carbs: 49, protein: 3.9, iron: '16%', }, { name: 'Jelly bean', calories: 375, fat: 0.0, carbs: 94, protein: 0.0, iron: '0%', }, { name: 'Lollipop', calories: 392, fat: 0.2, carbs: 98, protein: 0, iron: '2%', }, { name: 'Honeycomb', calories: 408, fat: 3.2, carbs: 87, protein: 6.5, iron: '45%', }, { name: 'Donut', calories: 452, fat: 25.0, carbs: 51, protein: 4.9, iron: '22%', }, { name: 'KitKat', calories: 518, fat: 26.0, carbs: 65, protein: 7, iron: '6%', }, ], } }, mounted() { const tableWrapper = this.$refs.tableRef.$el.querySelector('.v-table__wrapper'); const topScrollWrapper = this.$refs.topScrollWrapper; // 匹配表格容器的宽度和滚动属性 topScrollWrapper.style.width = tableWrapper.offsetWidth + 'px'; topScrollWrapper.style.overflowX = 'auto'; topScrollWrapper.style.overflowY = 'hidden'; // 创建占位元素,让滚动条正常显示 const scrollContent = document.createElement('div'); scrollContent.style.width = tableWrapper.scrollWidth + 'px'; scrollContent.style.height = '1px'; topScrollWrapper.appendChild(scrollContent); // 滚动同步逻辑 const syncScroll = (source, target) => { target.scrollLeft = source.scrollLeft; }; // 底部滚动时同步顶部 tableWrapper.addEventListener('scroll', () => syncScroll(tableWrapper, topScrollWrapper)); // 顶部滚动时同步底部 topScrollWrapper.addEventListener('scroll', () => syncScroll(topScrollWrapper, tableWrapper)); // 窗口 resize 时更新容器尺寸 window.addEventListener('resize', () => { topScrollWrapper.style.width = tableWrapper.offsetWidth + 'px'; scrollContent.style.width = tableWrapper.scrollWidth + 'px'; }); }, beforeUnmount() { // 清理事件监听,避免内存泄漏 const tableWrapper = this.$refs.tableRef?.$el?.querySelector('.v-table__wrapper'); const topScrollWrapper = this.$refs.topScrollWrapper; if (tableWrapper) tableWrapper.removeEventListener('scroll', () => {}); if (topScrollWrapper) topScrollWrapper.removeEventListener('scroll', () => {}); window.removeEventListener('resize', () => {}); } } </script> <style scoped> .top-scroll-wrapper { margin-bottom: -16px; /* 抵消滚动条高度,避免多出间距 */ pointer-events: auto; /* 允许点击顶部滚动条 */ } /* 可选:统一滚动条样式 */ .top-scroll-wrapper::-webkit-scrollbar, .v-table__wrapper::-webkit-scrollbar { height: 16px; } .top-scroll-wrapper::-webkit-scrollbar-track, .v-table__wrapper::-webkit-scrollbar-track { background: #f1f1f1; } .top-scroll-wrapper::-webkit-scrollbar-thumb, .v-table__wrapper::-webkit-scrollbar-thumb { background: #888; border-radius: 8px; } .top-scroll-wrapper::-webkit-scrollbar-thumb:hover, .v-table__wrapper::-webkit-scrollbar-thumb:hover { background: #555; } </style>
注意事项
- 如果使用Vuetify 3,表格滚动容器的类名是
.v-table-wrapper,需要把代码中的.v-table__wrapper替换成这个类名。 - 样式中的滚动条高度
16px是浏览器默认值,可根据需求调整。
内容的提问来源于stack exchange,提问作者Dev User
相关产品推荐
相关产品推荐

