antv表格大量數據卡頓問題(局部渲染數據)


  表格最大數據量也就500左右,再多,dom太多,瀏覽器會卡頓。為了解決這個問題,同時保持表格原有功能,對數據做了優化。

  特點:

  1、保留原有antv的table的所有功能(antd-react 一樣的道理,這里只貼vue代碼,react抄一下函數即可)

  2、數據切換流暢,無卡頓問題,頭尾數據無空白問題

  3、可視區域渲染數據,條數默認15條,可配置,注意和可視高度配合

  4、寫法很簡單

 思路: 默認每條數據高度一樣,不換行。增加一個滾動條,滾動滾動條,根據百分比,計算要展示的數據

 缺點:全選會觸發2次數據的回調,這個暫時沒處理;若表格換行,高度相差太大影響數據顯示,需要配置合理的高度

 

 貼一下代碼,有需要的自己拷貝:  ps:對分頁的一些功能還沒封裝完,直接忽略,看核心部分即可

<template>
  <div class="c-large-table">
    <a-table
      clas
      :loading="loading"
      :columns="columns"
      :row-key="record => record.id"
      :data-source="tableData"
      :row-selection="selected ? { selectedRowKeys: selectedRowKeys, onChange: handleSelect, onSelectAll: handleSelectAll } : null"
      @change="handleTableChange"
      :pagination="pagination"
    >
      <template slot="name" slot-scope="name"> {{ name.first }} {{ name.last }} </template>
    </a-table>
<!-- 虛擬滾動條 -->
    <div class="sc" :style="{height: tableHeight+'px'}">
      <div class="scbc" :style="{height: totalHeight+'px'}"></div>
    </div>
  </div>
</template>

<script>
const ROWS = 15,          // 局部渲染的數據條數
      HEIGHT = 29.6,      // 每行的高度
      TABLEHEIGHT = 446;  // 表格可視高度

export default {
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    dataSource: {
      type: Array,
      default: []
    },
    columns: {
      type: Array,
      default: []
    },
    pagination: {
      type: Object,
      default: {
        current: 1,
        pageSize: 20,
        tota: 0,
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: ["20", "50", "100", "200", "500", "1000", "2000"]
      }
    },
    rows: {   // 可視區域展示多少行
      type: Number,
      default: ROWS
    },
    rowHeight: { // 每行的高度
      type: Number,
      default: HEIGHT
    },
    tableHeight: { // 可是區域高度
      type: Number,
      default: TABLEHEIGHT
    },
    selected: { // 是否可選
      type: Boolean,
      default: false
    },
    selectChange: { // 可選的回調
      type: Function,
    },
  },
  data() {
    return {
      scrollEle: '',
      tableData: [],
      selectedRowKeys: [],
      totalHeight: 446,  // 數據總高度
      idx: 0,            // 當前開始下標
    };
  },
  watch: {
    dataSource () {
      const { dataSource, rows, rowHeight } = this
      this.tableData = dataSource.length > rows ? dataSource.slice(0, rows) : dataSource
      this.totalHeight = dataSource.length * rowHeight
    }
  },
  created() {
    const { dataSource, rows, rowHeight } = this
    this.tableData = dataSource.length > rows ? dataSource.slice(0, rows) : dataSource
    this.totalHeight = dataSource.length * rowHeight
  },
  mounted() {
    this.scrollEle = document.querySelector('.c-large-table .sc .scbc');
    document.querySelector('.c-large-table .sc').addEventListener('scroll', this.handleScroll);
  },
  methods: {
    onShowSizeChange(current, pageSize) {
      this.$emit("onShowSizeChange", current, pageSize);
    },
    pageChange(current, pageSize) {
      this.$emit("onChange", current, pageSize);
    },
    handleTableChange() {
      
    },

    handleSelect(d, dl) {
      this.selectedRowKeys = d
      if(this.selected) this.$emit("selectChange", d, dl);
    },
    // 注意全選,需要手動填充數據
    handleSelectAll(d,dl) {
      let keys = [], dates = []
      if(d) {
        keys = this.dataSource.map(item => item.id)
        dates = [...this.dataSource]
      }
      this.handleSelect(keys, dates)
    },
    // 監聽虛擬滾輪變化,計算展示的數據
    handleScroll(e) {
      const { scrollTop, scrollHeight } = e.target
      let lenMax = this.dataSource.length, nIdx;

      if(scrollTop === 0) {
        this.tableData = this.dataSource.slice(0, this.rows)
        this.idx = 0
      } else if(scrollTop === (scrollHeight - this.tableHeight)) {
        nIdx = lenMax - this.rows
        this.tableData = this.dataSource.slice(nIdx, nIdx + this.rows)
        this.idx = nIdx
      } else {
        nIdx = Math.ceil(scrollTop * lenMax / scrollHeight)
        if(nIdx !== this.idx && nIdx <= (lenMax - this.rows)) {
          this.tableData = this.dataSource.slice(nIdx, nIdx + this.rows)
          this.idx = nIdx
        }
      }
    },
  },
};
</script>

<style lang="less" >
  .c-large-table {
    position: relative;
    .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
      padding: 4px 10px;
    }
    .sc {
      position: absolute;
      top: 28px;
      right: -6px;
      width: 16px;
      overflow-x: hidden;
      overflow-y: scroll;
      .scbc {
        border-radius: 2px;
        background-color: #F1F1F1;
      }
    }
  }
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM