1.解决问题:不使用elementui table 中表格固定解决方案

        因为官网给出的方案只能在固定区域滚动,不能整页面滚动,对于数据量较大,项目较多的数据表不适用,浪费空间,所有想要整页面滚动。

 2.整页面滚动

        会出现表头缺失问题,不利于用户查找对于项内容。

3. 解决方案:当表格数据很多时,页面会出现滚动条,当表头滑动至页面顶部时,实现吸顶效果

 4.代码:

mounted() { //添加监听滚动条事件

window.addEventListener('scroll', this.handleScroll, true)

},

destroyed() { //移除(跳转页面后移除)

window.removeEventListener('scroll', this.handleScroll, true)

},

methods: {

handleScroll(e) {

//content-box 为包裹表格的外层盒子

let heightTop = document.getElementsByClassName('content-box')[0].scrollTop //距离顶部高度

if (heightTop >= 146) { //表头到达页面顶部固定表头

// 146 为距离顶部多少时开始吸顶,即吸顶距离

let top = heightTop - 146

document.getElementsByClassName('el-table__header-wrapper')[0].style.zIndex = '9999'

document.getElementsByClassName('el-table__header-wrapper')[0].style.top = `${top}px`

// 有固定列时,改变固定列的top

let fixedWrapper = document.getElementsByClassName('el-table__fixed-header-wrapper')

for (let i in fixedWrapper) {

document.getElementsByClassName('el-table__fixed-header-wrapper')[i].style.top = `${top}px`

document.getElementsByClassName('el-table__fixed-header-wrapper')[i].style.zIndex = '9999'

}

} else {

document.getElementsByClassName('el-table__header-wrapper')[0].style.top = ''

document.getElementsByClassName('el-table__header-wrapper')[0].style.zIndex = ''

let fixedWrapper = document.getElementsByClassName('el-table__fixed-header-wrapper')

for (let i in fixedWrapper) {

document.getElementsByClassName('el-table__fixed-header-wrapper')[i].style.top = ''

document.getElementsByClassName('el-table__fixed-header-wrapper')[i].style.zIndex = '3'

}

}

},

}

5.原理

        对于普通表头,定位方式为relative,不断监听外层包裹盒子滚动的高度,并对于改变top值,就会实现。

        对于固定表头(fixed),定位方式为absolute,不断监听外层包裹盒子滚动的高度,并对于改变top值,也会实现。

        注:查看elementui中是否加了上文所述定位,如果没有,请自行添加合适的定位方式。

### 借鉴方法,挺好用

1.新建文件 table-sticky.js, 直接复制即可。

/* 组件需要提供parent字段,指定表格的className(字符串) */

const rafThrottle = (fn) => {

let locked = false;

return function (...args) {

if (locked) return;

locked = true;

window.requestAnimationFrame(_ => {

fn.apply(this, args);

locked = false;

});

};

}

export default {

mounted() {

this.containerDom = document.getElementsByClassName('main-container')

this.clearListener()

let timer = setTimeout(() => {

this.initFixedHeader()

clearTimeout(timer)

}, 300)

window.addEventListener('resize', this.resizeChange)

},

deactivated() {

this.clearListener()

},

beforeDestroy() {

this.clearListener()

//取消监听窗口大小

window.removeEventListener('resize', this.resizeChange)

},

activated() {

this.initFixedHeader()

this.updateFixedRight()

window.addEventListener('resize', this.resizeChange)

let timer

timer = setTimeout(() => {

let container = this.containerDom

if (container[0].scrollTop > 0) {

container[0].scrollTop = container[0].scrollTop + 2

}

clearTimeout(timer)

}, 1000)

},

methods: {

activatedReload() {

window.addEventListener('resize', this.resizeChange)

let timer = setTimeout(() => {

this.clearFixedStyle()

this.initFixedHeader()

}, 300)

this.timerList.push(timer)

},

reset() {

this.clearFixedStyle()

},

// 窗口大小变化时,初始化

resizeChange() {

this.headerDragend()

let timer = setTimeout(() => {

this.initFixedHeader()

clearTimeout(timer)

}, 300)

},

async initFixedHeader() {

if (this.parent) {

// console.log('启动监听,页面:', this.parent)

this.parentDom = document.getElementsByClassName(this.parent)

if (this.parentDom && this.parentDom.length !== 0) {

this.tableWidth = this.parentDom[0].querySelector('.el-table__header-wrapper').getBoundingClientRect().width

this.setScrollXWidth()

this.tableDom = this.parentDom[0].getElementsByClassName('el-table__header-wrapper')

this.scrollDom = document.querySelector('.main-container')

this.scrollDom.addEventListener('scroll', this.scrollEvent)

}

}

},

// 清空监听事件

clearListener() {

if (this.scrollDom) {

this.scrollDom.removeEventListener('scroll', this.scrollEvent)

window.removeEventListener('resize', this.resizeChange)

this.clearFixedStyle()

// console.log('卸载监听,页面:', this.parent)

this.timerList.forEach(key => {

clearTimeout(key)

});

}

},

// 更新右侧固定栏

updateFixedRight() {

let { fixedRightHeaderDom, dom } = this.getFixedDom()

if (dom.classList.contains('fixed')) {

let timer = setTimeout(() => {

this.setFixedStyle({

dom: fixedRightHeaderDom,

left: this.fixedRightDom[0].getBoundingClientRect().left + 'px',

width: getComputedStyle(this.fixedRightDom[0]).width,

scrollLeft: fixedRightHeaderDom.scrollWidth

})

clearTimeout(timer)

}, 100)

}

},

async headerDragend() {

await this.updateWidth()

await this.updateFixedRight()

this.setScrollXWidth()

// await this.updateHeaderHeight()

},

setScrollXWidth() {

let timer = setTimeout(() => {

if (!this.parentDom) this.parentDom = document.getElementsByClassName(this.parent)

if (this.parentDom.length == 0) return

let dom = this.parentDom[0].querySelector('.el-table__header')

this.tableWidth = this.parentDom[0].querySelector('.el-table__body-wrapper').getBoundingClientRect().width

this.tableDom[0].style.width = this.tableWidth + 'px'

this.updateHeaderHeight()

this.headerWidth = dom.style.width

clearTimeout(timer)

}, 200)

},

// 更新表格宽度,(拖拽改变宽度时使用)

updateWidth() {

if (!this.parentDom) this.parentDom = document.getElementsByClassName(this.parent)

const bodyWrapperDom = this.parentDom[0].getElementsByClassName('el-table__body-wrapper')[0]

const width = getComputedStyle(bodyWrapperDom).width//表格宽度

// 给表格设置宽度。

const tableParent = this.tableDom

for (let i = 0; i < tableParent.length; i++) {

tableParent[i].style.width = width

}

},

getFixedDom() {

let fixedRightHeaderDom, fixedRightBox, fixedLeftHeaderDom, fixedLeftBox;

let dom = this.tableDom[0]

if (this.fixedLeftDom && this.fixedLeftDom[0]) {

let lefarr = this.fixedLeftDom[0].children

fixedLeftHeaderDom = lefarr[0]

fixedLeftBox = lefarr[1]

}

if (this.fixedRightDom && this.fixedRightDom[0]) {

let rightarr = this.fixedRightDom[0].children

fixedRightHeaderDom = rightarr[0]

fixedRightBox = rightarr[1]

}

return { fixedRightHeaderDom, fixedRightBox, fixedLeftHeaderDom, fixedLeftBox, dom }

},

// 更新表头高度,表头高度有可能改变

updateHeaderHeight() {

this.$nextTick(() => {

this.tableDom = this.parentDom[0].getElementsByClassName('el-table__header-wrapper')

let obj = this.tableDom[0].getBoundingClientRect()

if (obj.height != this.tablexy.height) {

this.tablexy.height = obj.height

let { dom } = this.getFixedDom()

if (dom.classList.contains('fixed')) {

let timer = setTimeout(() => {

this.parentDom[0].getElementsByClassName('el-table__fixed-body-wrapper')[0].style.top = 0

let container = this.containerDom

if (container && container[0]) {

container[0].scrollTop = container[0].scrollTop + 3;

}

clearTimeout(timer)

}, 100)

}

}

})

},

// 获取表格属性

getTableXy() {

this.tablexy = this.tableDom[0].getBoundingClientRect()

this.tablexy.height = this.tableDom[0].offsetHeight

return this.tablexy

},

getDom() {

if (!this.parentDom) {

this.parentDom = document.getElementsByClassName(this.parent)

}

},

//滚动事件

scrollEvent: rafThrottle(async function (e) {

this.getDom()

this.tableDom = this.parentDom[0].getElementsByClassName('el-table__header-wrapper')

if (this.tablexy.top == 0 || !this.tablexy.height || !this.tablexy.top) {

await this.getTableXy()

}

this.fixedRightDom = this.parentDom[0].getElementsByClassName('el-table__fixed-right')

this.fixedLeftDom = this.parentDom[0].getElementsByClassName('el-table__fixed')

let { height, top, left } = this.tablexy

let scrollTop = e.target.scrollTop

let { fixedRightHeaderDom, fixedRightBox, fixedLeftHeaderDom, fixedLeftBox, dom } = this.getFixedDom()

// 距离顶部多少距离时开始固定

if (scrollTop >= height / 2 + top) {

// 存在右侧固定表头

if (fixedRightHeaderDom) {

this.setFixedStyle({

dom: fixedRightHeaderDom,

left: this.fixedRightDom[0].getBoundingClientRect().left + 'px',

width: getComputedStyle(this.fixedRightDom[0]).width,

scrollLeft: fixedRightHeaderDom.scrollWidth

})

fixedRightBox.style.top = 0

}

// 左侧固定

if (fixedLeftHeaderDom) {

this.setFixedStyle({

dom: fixedLeftHeaderDom,

left: left + 'px',

width: getComputedStyle(this.fixedLeftDom[0]).width,

scrollLeft: 0

})

fixedLeftBox.style.top = 0

}

dom.classList.add('fixed')//加一个固定标识

this.updateWidth()

dom.style.position = 'fixed'

dom.style.zIndex = '2000'

// 固定时距顶部距离

dom.style.top = 0 + 'px'

dom.style.overflow = 'hidden'

} else {

this.clearFixedStyle()

}

}),

//设置固定

setFixedStyle(data) {

let { dom, scrollLeft, width, left } = data

dom.style.zIndex = '2000'

dom.style.position = 'fixed'

// 固定时距顶部距离

dom.style.top = 0 + 'px'

dom.scrollLeft = scrollLeft

dom.style.width = width

dom.style.overflow = 'hidden'

dom.style.left = left

},

// 清除header固定

clearFixedStyle() {

if (!this.tableDom) return

let { height, left } = this.tablexy

let { dom, fixedRightHeaderDom, fixedRightBox, fixedLeftHeaderDom, fixedLeftBox } = this.getFixedDom()

if (dom.classList.contains('fixed')) {

if (fixedRightHeaderDom) {

fixedRightBox.style.top = height + 'px'

fixedRightHeaderDom.removeAttribute("style");

}

if (fixedLeftHeaderDom) {

fixedLeftHeaderDom.style.zIndex = '0'

fixedLeftHeaderDom.style.position = 'static'

fixedLeftHeaderDom.style.top = 0 + 'px'

fixedLeftHeaderDom.style.left = left + 'px'

fixedLeftBox.style.top = getComputedStyle(dom).height

}

dom.classList.remove('fixed')

dom.style.position = 'static'

dom.style.top = '0'

dom.style.zIndex = '0'

}

},

},

computed: {

__opened() {

return this.$store.state.app.sidebar.opened

}

},

watch: {

__opened() {

this.$nextTick(() => {

this.setScrollXWidth()

})

}

},

data() {

return {

tablexy: {},//表格的左边宽度信息

fixedRightDom: null,//右侧

fixedLeftDom: null,//左侧栏固定

scrollDom: null,//滚动的dom

parentDom: null,//表格的父元素dom

tableWidth: 0,

timerList: [],

tableDom: null,

containerDom: null

}

},

}

 2.出现滚动条的容器中添加类名 class="main-container"

 

3. 表格文件中使用mixin引入table-sticky.js

....

import stacky from '@/common/table-sticky'

export default {

mixins: [stacky],

data() {

return {

// 包裹table标签的外层div加上类

parent: 'self-table',

}

}

}

注:1.根据项目需求,自行调整吸顶高度。

        2.表格上方元素高度变化时,可能会产生bug,此时需要调整代码。 

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。