一.使用方式
在main.ts页面创建 vue指令
typescript
import { createSticky } from '@/utils/sticky'
const app = createApp(App)
createSticky(app)
...
app.mount('#app');
在el-table标签上使用 v-sticky
html
<div class="table-box">
<!--此处的 .table-box 是会出现滚动条的DOM元素通过document.querySelector选择器进行监听滚动条,如果不传则监听document.querySelector('body')的滚动条
-->
<el-table v-sticky="{ top: 50, parent: '.table-box'}" >
....
</el-table>
<div>
通过以上使用方式,el-table就可以进行吸顶了。
二.脚本文件
复制并保存以下脚本内容到 utils文件夹。
javascript
/**
* 思路:通过简体 el-table的 thead和tbody父级别区域,进行设置对于的fixed
*/
function getElParentBySelector(el: any, queryClassSelector: string) {
if (!el) {
return el
}
if ([...el.classList].includes(queryClassSelector)) {
return el
}
return getElParentBySelector(el.parentNode, queryClassSelector)
}
function getTableShowWidth(thead: string) {
const tableBox = getElParentBySelector(thead, 'el-table')
return tableBox.getBoundingClientRect().width
}
function createTableSticky(el: any, binding: any, vNode?: any) {
// 获取表格(element)
let thead = el.querySelector('.el-table__header')
thead = getElParentBySelector(thead, 'el-table__header-wrapper')
const tbody = el.querySelector('.el-table__body')
//获取thead 的显示宽度
const headerShowWidth = getTableShowWidth(thead)
// 获取滚动元素
const scrollParent = document.querySelector(binding.value.parent||'body')
if (!scrollParent || binding.value.disabled === true) {
return
}
scrollParent.addEventListener('scroll', function () {
const stickyTop= binding.value.top||0;
const theadHeight = thead.clientHeight
// 获取thead距离顶部的距离
const theadTop = thead.getBoundingClientRect().top
if (theadTop <= stickyTop) {
tbody.style.paddingTop = theadHeight + 'px'
thead.style.position = 'fixed'
thead.style.zIndex = '2021'
thead.style.top = stickyTop + 'px'
thead.style.borderTop = '1px solid #EBEBEB'
//thead.style.width = tbody.offsetWidth + 'px' //
//使用最佳显示宽度显示内容,防止有横向滚动条时,固定列显示超出
thead.style.width =
(tbody.offsetWidth < headerShowWidth ? tbody.offsetWidth : headerShowWidth) + 'px'
//获取父级别的宽度,设置列头行只能是负极宽度
}
// 判断是否需要回归原来位置
const originally = tbody.getBoundingClientRect().top
// 判断底部距离是否超过表头
const goBeyond = tbody.getBoundingClientRect().bottom
if (originally > stickyTop || goBeyond <= thead.offsetHeight) {
tbody.style.paddingTop = '0'
thead.style.position = 'relative'
thead.style.zIndex = '0'
thead.style.top = 0 + 'px'
thead.style.width = tbody.offsetWidth + 'px'
thead.style.borderTop = 'none'
}
})
}
export function createSticky(vue: any) {
let clearTimeId = 0
// el-table表头吸顶效果
vue.directive('sticky', {
// 当被绑定的元素插入到 DOM 中时......
mounted(el: any, binding: any) {
//TIP 延时设置,确保表格进行渲染成功!
clearTimeId = setTimeout(() => {
createTableSticky(el, binding)
clearTimeout(clearTimeId)
}, 1000)
},
update(el: any, binding: any) {
//TIP 延时设置,确保表格进行渲染成功!
clearTimeId = setTimeout(() => {
createTableSticky(el, binding)
clearTimeout(clearTimeId)
}, 1000)
},
unmounted(el: any, binding: any) {
clearTimeId && clearTimeout(clearTimeId)
}
})
}