炫彩代码 2021-06-12 10:44 采纳率: 0%
浏览 3118

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

<template>
  <a-table :columns="columns"
           :data-source="data"
           :pagination="pagination"
           :scroll="{ x: 1500, y: 300 }">
    <a slot="action">action</a>
  </a-table>
</template>
<script>
const columns = [
  {
    title: 'Full Name',
    width: 100,
    dataIndex: 'name',
    key: 'name',
    fixed: 'left'
  },
  { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
  { title: 'Column 1', dataIndex: 'address', key: '1', width: 150 },
  { title: 'Column 2', dataIndex: 'address', key: '2', width: 150 },
  { title: 'Column 3', dataIndex: 'address', key: '3', width: 150 },
  { title: 'Column 4', dataIndex: 'address', key: '4', width: 150 },
  { title: 'Column 5', dataIndex: 'address', key: '5', width: 150 },
  { title: 'Column 6', dataIndex: 'address', key: '6', width: 150 },
  { title: 'Column 7', dataIndex: 'address', key: '7', width: 150 },
  { title: 'Column 8', dataIndex: 'address', key: '8' },
  {
    title: 'Action',
    key: 'operation',
    fixed: 'right',
    width: 100,
    scopedSlots: { customRender: 'action' }
  }
]

const data = []
for (let i = 0; i < 100; i++) {
  data.push({
    key: i,
    name: `Edrward ${i}`,
    age: 32,
    address: `London Park no. ${i}`
  })
}

export default {
  data() {
    return {
      data,
      columns,
      pagination: {
        pageSizeOptions: ['10', '20', '30', '50', '100'], //每一页可选显示条数
        pageSize: 100, // 每一页条数
        total: 46, //总条数
        showTotal: (total) => `共 ${total} 条`, //显示总条数
        showSizeChanger: true
      }
    }
  }
}
</script>

当表格条数很多时,这种不同步滚动就更加明显

鼠标在固定列滚动不会出现不同步问题,但是在非固定列就会非常的明显

  • 写回答

10条回答 默认 最新

  • 穿云路 2022-08-05 09:47
    关注

    // 根据Foxmiy的思路 在业务层重写了 handleWheel方法 在不升级的情况下可以正常作用到所有的table组件
    // 写一个mixins文件 然后注入到全局即可

    // 声明一个变量用来防止多个组件多次注册同一事件 会导致元素挂载太多同一事件导致页面卡顿
    let isBindScrollWheel = false
    // 白名单 需要做这个操作的页面 把 组件的 name 属性填入此名单
    const PageWhiteList = ['TestData', 'TestXXXt', 'XXX' ]
    
    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;
          }
        },
      }
    }
    
    
    评论 编辑记录

报告相同问题?