antd-vue 中table设置左右固定列后,在滚动时会出现不同步的问题

1,657 阅读1分钟

根据链接 ask.csdn.net/questions/7… 提供的思路 在不用升级插件版本和修改插件源码的情况下,在业务层重写底层的DOM原生方法,达到同样的效果

写一个mixins文件

// 声明一个变量用来防止多个组件多次注册同一事件 会导致元素挂载太多同一事件导致页面卡顿
let isBindScrollWheel = false
// 白名单 需要做这个操作的页面 把 组件的 name 属性填入此名单
const PageWhiteList = ['Testxxx', 'Reportxxx', 'xxxx', 'Managexxx']

export default {
  mounted() {
    if (!PageWhiteList.includes(this.$options.name)) return
    this.$nextTick(() => {
      this.addScrollWheelToTable()
    })
  },
  beforeDestroy() {
    this.removeScrollWheelFromTable()
  },
  methods: {
    // 移除相关元素的相关事件和清空全局数据
    removeScrollWheelFromTable() {
      if (!PageWhiteList.includes(this.$options.name)) return
      if (this._allTableContainers && this._allTableContainers.length) {
        for (let i = 0; i < this._allTableContainers.length; i++) {
          const item = this._allTableContainers[i]
          item.removeEventListener('scroll', this.handleScrollCustom)
          item.removeEventListener('wheel', this.handleWheelCustom)
        }
        this._allTableContainers = null
        this._lastTableScrollTop = null
        isBindScrollWheel = false
      }
    },
    // 
    /**
     * 给ant-design-vue的table组件中 有fixed属性的 元素
     *  1、重写源码中的 handleWheel 事件 
     *    具体位置在 node_modules\ant-design-vue\es\vc-table\src\Table
          if (window.navigator.userAgent.match(/Trident/7./) && scroll.y) 改为 if (scroll.y)
        2、重写源码中的 handleBodyScroll 事件 
          为了在 handleWheel 事件中使用一个 _lastTableScrollTop 变量
     * @returns void
     */
    addScrollWheelToTable() {
      if (isBindScrollWheel) return
      // 找到 fixed 元素下在相关元素(左右fixed的列) .ant-table-fixed-left/.ant-table-fixed-right 元素下的 .ant-table-body-inner
      const innerFixeds = document.querySelectorAll('.ant-table-body-inner')
      // 找到原有的 table 固定区域
      const innerBody = document.querySelector('.ant-table-body')
      // 给所有相关的元素再加一次
      if (innerFixeds.length) {
        this._allTableContainers = [...innerFixeds]
        if (innerBody) {
          this._allTableContainers.push(innerBody)
        }
        for (let i = 0; i < this._allTableContainers.length; i++) {
          const item = this._allTableContainers[i]
          item.addEventListener('scroll', this.handleScrollCustom)
          item.addEventListener('wheel', this.handleWheelCustom)
        }
        isBindScrollWheel = true
      }
    },
    handleScrollCustom(e) {
      var target = e.target;
      e.preventDefault()
      // Remember last scrollTop for scroll direction detecting.
      this._lastTableScrollTop = target.scrollTop;
    },
    handleWheelCustom(event) {
      const ref_bodyTable = document.querySelector('.ant-table-scroll .ant-table-body')
      const ref_fixedColumnsBodyLeft = document.querySelector('.ant-table-fixed-left .ant-table-body-inner')
      const ref_fixedColumnsBodyRight = document.querySelector('.ant-table-fixed-right .ant-table-body-inner')
      event.preventDefault();
      var wd = event.deltaY;
      var target = event.target;
      var bodyTable = ref_bodyTable,
        fixedColumnsBodyLeft = ref_fixedColumnsBodyLeft,
        fixedColumnsBodyRight = ref_fixedColumnsBodyRight;

      var scrollTop = 0;
      if (this._lastTableScrollTop) {
        scrollTop = this._lastTableScrollTop + wd;
      } else {
        scrollTop = wd;
      }
      if (fixedColumnsBodyLeft && target !== fixedColumnsBodyLeft) {
        fixedColumnsBodyLeft.scrollTop = scrollTop;
      }
      if (fixedColumnsBodyRight && target !== fixedColumnsBodyRight) {
        fixedColumnsBodyRight.scrollTop = scrollTop;
      }
      if (bodyTable && target !== bodyTable) {
        bodyTable.scrollTop = scrollTop;
      }
    },
  }
}

封装成vue插件 index.js

import ScrollWheelMixins from './mixins'

export default {
  install (Vue) {
    Vue.mixin(ScrollWheelMixins)
  }
}

引入全局

import antdvueTableScrollWheel from '../plugins/xxxx'
Vue.use(antdvueTableScrollWheel)

完美实现 同步滚动