123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /* 组件需要提供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: {
- 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 = 83 + 'px'
- }
- // 左侧固定
- if (fixedLeftHeaderDom) {
- this.setFixedStyle({
- dom: fixedLeftHeaderDom,
- left: left + 'px',
- width: getComputedStyle(this.fixedLeftDom[0]).width,
- scrollLeft: 0
- })
- fixedLeftBox.style.top = 83 + 'px'
- }
- dom.classList.add('fixed') //加一个固定标识
- this.updateWidth()
- dom.style.position = 'fixed'
- dom.style.zIndex = '2000'
- dom.style.top = 83 + '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 = 83 + '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'
- }
- }
- },
- 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
- }
- }
- }
|