基于ElementUI的el

您所在的位置:网站首页 表格中筛选时固定表头 基于ElementUI的el

基于ElementUI的el

#基于ElementUI的el| 来源: 网络整理| 查看: 265

仓库https://github.com/LSZ579/element-table-sticky

具体需求 在使用el-table时,表格高度自适应(不出现双滚动条,仅body有滚动条),滚动到表头的位置时自动吸附在顶部。 实现原理 在尝试了几种方法之后,其他方法都不支持左右固定栏(fixed),所以最终采用了监听滚动事件的方案,采用了mixins混入方案,只测试vue2.0,不建议使用全局混入,vue3估计需要调整** 1、通过监听滚动事件、获取表头的高度,位置,在特定的情况下修改el-table-header的style属性 2、由于考虑到使用keep-alive,所以每个表格组件都需要加一个唯一的class值,用于获取当前唯一的表格的dom

作者:小陆pro 链接:https://juejin.cn/post/7086710574695858206 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 使用方法 1.设置滚动的节点 sticky-table.js文件

scrollClass:'.main-container',//设置滚动的body

注意把滚动的body设置成可滚动

.main-container { height: 100vh !important; overflow: auto; }

2.引入并注入sticky-table mixins,设置当前表格组件的父元素class,即parent headerWidth是用于生成自定义表格滚动条的(固定在底部,详情看git上的例子)

import stacky from '@/utils/table-sticky' export default{ mixins: [stacky], data() { return { tableColumns: [], tableData: [], headerWidth: 0, parent: 'self-table', tableWidth:0 } }, }

3、暴露出来的方法,可直接this.xx调用,大多数用于动态修改表头或者拖动的时候,需要更新表格样式

在这里插入图片描述 4、加入模拟表格滚动条固定到底部 实例上有提供该组件(virtualScroll), 方法setScrollXWidth是计算滚动条的宽度的,headerWidth是表头实际长度,tableWidth是表头可视的宽度

/* 组件需要提供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._initSticky() }, 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: { /* 初始化 */ _initSticky() { this.containerDom = document.getElementsByClassName('main-container') this.clearListener() let timer = setTimeout(() => { this.initFixedHeader() clearTimeout(timer) }, 300) window.addEventListener('resize', this.resizeChange) }, activatedReload() { window.addEventListener('resize', this.resizeChange) let timer = setTimeout(() => { this.clearFixedStyle() this.initFixedHeader() }, 300) this.timerList.push(timer) }, // 窗口大小变化时,初始化 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 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' dom.scrollLeft = scrollLeft dom.style.width = width dom.style.overflow = 'hidden' dom.style.left = left }, // 重置样式 reset() { this.clearFixedStyle() }, // 清除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 } }, }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3