elTable实现无限无缝滚动-自用记录📝

92 阅读1分钟

使用elTable组件 实现表格的无限无缝滚动

<el-table
          ref="materialTable"
          :data="materialData"
          height="190"
          style="margin-top: 5px"
          @mouseenter.native="handleMaterialTableMouseEnter"
          @mouseleave.native="handleMaterialTableMouseLeave"
          >
  <el-table-column prop="firClassName" label="一级名称" align="center" show-overflow-tooltip min-width="180px"></el-table-column>
  <el-table-column prop="secClassName" label="二级名称" align="center" show-overflow-tooltip min-width="140px"></el-table-column>
  <el-table-column prop="receiveRate" label="收料完成率" :formatter="(_, _2, cellValue) => cellValue + '%'" align="center" sortable></el-table-column>
</el-table>
private materialAutoScrollTimer: number | null = null
private isMaterialScrolling = true
private materialAnimationFrameId: number | null = null
// 获取滚动容器(提取公共方法)
private getMaterialScrollWrapper () {
  return this.$refs.materialTable?.$el.querySelector('.el-table__body-wrapper')
}
// 鼠标移入表格时停止自动滚动
handleMaterialTableMouseEnter () {
  this.stopMaterialAutoScroll()
  this.removeMaterialTableBody()
}
// 鼠标移出表格时开始自动滚动
handleMaterialTableMouseLeave () {
  this.startMaterialAutoScroll()
}
// 克隆表格体
cloneMaterialTableBody () {
  const wrapper = this.getMaterialScrollWrapper()
  if (wrapper) {
    const tableBody = wrapper.querySelector('tbody')
    if (tableBody && !tableBody.nextElementSibling) {
      // 避免重复克隆
      const cloneBody = tableBody.cloneNode(true) as HTMLElement
      tableBody.parentNode.appendChild(cloneBody)
    }
  }
}
// 移除克隆的表格体
removeMaterialTableBody () {
  const wrapper = this.getMaterialScrollWrapper()
  if (wrapper) {
    const tableBody = wrapper.querySelector('tbody')
    if (tableBody && tableBody.nextElementSibling) {
      tableBody.parentNode.removeChild(tableBody.nextElementSibling)
    }
  }
}
// 新增自动滚动方法
startMaterialAutoScroll () {
  this.stopMaterialAutoScroll()
  const wrapper = this.getMaterialScrollWrapper()
  if (wrapper && wrapper.scrollHeight > wrapper.clientHeight) {
    wrapper.classList.add('no-scroll')
    this.cloneMaterialTableBody()
    this.isMaterialScrolling = true
    // 获取原始表格高度
    const originalHeight = wrapper.scrollHeight / 2
    const animate = () => {
      if (!this.isMaterialScrolling || !wrapper) return
      const { scrollTop } = wrapper
      const newScrollTop = scrollTop + 0.8
      // 当滚动超过原始高度时无缝重置
      if (newScrollTop >= originalHeight) {
        wrapper.scrollTop = newScrollTop - originalHeight
      } else {
        wrapper.scrollTop = newScrollTop
      }
      this.materialAnimationFrameId = requestAnimationFrame(animate)
    }
    this.materialAnimationFrameId = requestAnimationFrame(animate)
  }
}
// 停止自动滚动方法
stopMaterialAutoScroll () {
  const wrapper = this.getMaterialScrollWrapper()
  if (wrapper) wrapper.classList.remove('no-scroll')
  this.isMaterialScrolling = false
  if (this.materialAnimationFrameId) {
    cancelAnimationFrame(this.materialAnimationFrameId)
    this.materialAnimationFrameId = null
  }
  if (this.materialAutoScrollTimer) {
    clearInterval(this.materialAutoScrollTimer)
    this.materialAutoScrollTimer = null
  }
}
::v-deep .no-scroll {
  overflow: hidden !important;
}