SOURCE

<template>
    <div class="my-table"  
     v-loading="isLoading" 
    element-loading-text="拼命加载中..."
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(7, 11, 44, 0.8)">
      <!-- el-table 增加key 重新生成实例会重置滚动条位置回复初始位置 -->
      <el-table
        :key="isLoading"
        ref="table"
        :data="getTableData"
        :empty-text="isLoading ? '' : '暂无数据'"
        style="width: 100%"
        height="99.9%"
      >
        <el-table-column
          v-for="(item, index) in tableHeader"
          :key="index"
          :prop="item.prop"
          :label="item.label"
          align="center"
          :show-overflow-tooltip="true"
          min-width="110px"
        >
        </el-table-column>
      </el-table>
    </div>
</template>

<script>

export default {
  data () {
    return {
      currentIndex: 1, // 定位截取索引
      isLoading: false,
      tableHeader: [{
        prop: 'name',
        label: '区域'
      }, {
        prop: 'cameraNum',
        label: '摄像头数'
      }, {
        prop: 'onlineNum',
        label: '在线数'
      }, {
        prop: 'offlineNum',
        label: '离线数'
      }, {
        prop: 'noCamera',
        label: '无摄像头'
      }], // 表格的表头
      tableData: [] // 表格的值
    }
  },
  methods: {
    async updateTableData (code = '', level = '') {
      this.tableData = []
      this.currentIndex = 1
      this.isLoading = true
      const res = await new Promise((reslove,reject)=>{
        setTimeout(() => {
          reslove({
            data: Array(1000).fill({}).map((item,index)=>({index}))
          }) // 模拟大数据量
        }, 1000);
      }) 
      this.tableData = res.data
      this.isLoading = false
      this.virtualScroll() // 虚拟滚动处理:大数据量
    },
    virtualScroll () {
      if (!this.tableData.length) {
        return
      }
      this.$nextTick(() => {
        const elBodyWrapper = this.$refs.table.$el.querySelector('.el-table__body-wrapper') // 滚动容器dom
        const h = elBodyWrapper.querySelectorAll('.el-table__cell')[0].offsetHeight // 单行高度
        // 方案1:动态增加标签,给标签设置高度,从而撑开容器elBodyWrapper整体高度
        /**********方案1代码开始**********/
        const i = document.createElement('i') // 通过一个标签撑开容器内容
        i.style.width = '0'
        i.style.height = this.tableData.length * h + 'px' // 设置容器内容整体高度
        elBodyWrapper.append(i)        
        // 添加滚动监听
        elBodyWrapper.addEventListener('scroll', () => {
          let s = elBodyWrapper.scrollTop // 滚动条位置
          const c = Math.floor(s / h) //  滚动后定位索引
          // 判断是否存在横向滚动条时且处于置底时
          if (s >= (this.tableData.length * h) - elBodyWrapper.offsetHeight - 16) {
            s = (this.tableData.length * h) - elBodyWrapper.offsetHeight
          }
          if (s <= 0) {
            s = 0
          }
          // 更新定位索引
          this.currentIndex = c + 1
          elBodyWrapper.querySelector('.el-table__body').style.transform = `translateY(${s}px)` 
        })
         /**********方案1代码结束**********/

          // 方案2:给el-table__body设置一个动态的paddingTop值,视觉上做一个虚拟占位(必须保持一个较大的截取长度,保证初始表格出现滚动条,否则该方案存在问题)
        /**********方案2代码开始**********/   
        // 添加滚动监听
        elBodyWrapper.addEventListener('scroll', () => {
          let s = elBodyWrapper.scrollTop // 滚动条位置
          const c = Math.floor(s / h) //  滚动后定位索引
          // 判断是否存在横向滚动条时且处于置底时
          if (s >= (this.tableData.length * h) - elBodyWrapper.offsetHeight - 16) {
            s = (this.tableData.length * h) - elBodyWrapper.offsetHeight
          }
          if (s <= 0) {
            s = 0
          }
          // 更新定位索引
          this.currentIndex = c + 1
          elBodyWrapper.querySelector('.el-table__body').style.paddingTop = `${s}px`
        })
         /**********方案2代码结束**********/
      })
    }
  },
  computed: {
    getTableData () {
      // 每次根据定位索引currentIndex截取16位长度的数组数据
      return this.tableData.slice(this.currentIndex - 1, this.currentIndex + 15)
    }
  },
  mounted () {
    this.updateTableData()
  }
}
</script>

<style lang="less" scoped>
</style>
console 命令行工具 X clear

                    
>
console