// 工具函数:获取 .el-table__body-wrapper 下的滚动容器 function getBodyWrapper(el) { return el.querySelector('.el-table__body-wrapper'); } // 创建滚动条并绑定事件,返回清理函数 function setupScrollSync(el) { const table = el; // el 就是容器元素 if (!table) return null; const outerWidth = table.offsetWidth; // 取第一个内部 table 的宽度作为内容宽度 const innerTable = table.querySelector('table'); const contentWidth = innerTable ? innerTable.offsetWidth : outerWidth; const bodyWrapper = getBodyWrapper(table); if (!bodyWrapper) { console.warn('未找到 .el-table__body-wrapper,无法创建滚动同步'); return null; } // 隐藏原生横向滚动条,但保留纵向滚动条 bodyWrapper.style.overflowX = 'hidden'; bodyWrapper.style.overflowY = 'auto'; // 创建自定义样式标签来隐藏横向滚动条 const styleId = 'v-scroll-sync-hide-x-scrollbar'; let styleEl = document.getElementById(styleId); if (!styleEl) { styleEl = document.createElement('style'); styleEl.id = styleId; styleEl.textContent = ` .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar { width: 6px; height: 0; } .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar-track { background: transparent; } .el-table__body-wrapper.v-scroll-sync-hide-x::-webkit-scrollbar-thumb { background: #d9d9d9; border-radius: 3px; } `; document.head.appendChild(styleEl); } bodyWrapper.classList.add('v-scroll-sync-hide-x'); // 避免重复创建 const existingDiv = table.querySelector('.v-scroll-sync-bar'); if (existingDiv) existingDiv.remove(); const div = document.createElement('div'); div.className = 'v-scroll-sync-bar'; div.style.width = outerWidth + 'px'; div.style.height = '12px'; div.style.overflowX = 'auto'; div.innerHTML = `
`; const onScroll = () => { bodyWrapper.scrollLeft = div.scrollLeft; }; div.addEventListener('scroll', onScroll); const tableContainer = table.querySelector('.el-table'); // 在tableContainer后面插入div(作为兄弟元素) tableContainer.insertAdjacentElement('afterend', div); // table.appendChild(div); // 返回清理函数和事件引用 return { div, bodyWrapper, handler: onScroll, destroy() { div.removeEventListener('scroll', onScroll); if (div.parentNode) div.parentNode.removeChild(div); // 移除添加的class bodyWrapper.classList.remove('v-scroll-sync-hide-x'); } }; } // Vue 2 自定义指令 const tableScrollSync = { bind(el) { // bind 时可能未插入文档,先不做操作,统一在 inserted 中处理 el._scrollSyncData = null; }, inserted(el) { // 元素插入 DOM 后初始化 el._scrollSyncData = setupScrollSync(el); }, update(el) { // 当表格数据变化导致内容宽度改变时(如切换分页、动态列),重新初始化 if (el._scrollSyncData) { el._scrollSyncData.destroy(); } el._scrollSyncData = setupScrollSync(el); }, unbind(el) { // 指令解绑时销毁 if (el._scrollSyncData) { el._scrollSyncData.destroy(); el._scrollSyncData = null; } } }; export default tableScrollSync;