国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

vue+element-ui el-table組件二次封裝實現(xiàn)虛擬滾動,解決數(shù)據(jù)量大渲染DOM過多而卡頓問題

這篇具有很好參考價值的文章主要介紹了vue+element-ui el-table組件二次封裝實現(xiàn)虛擬滾動,解決數(shù)據(jù)量大渲染DOM過多而卡頓問題。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、此功能已集成到TTable組件中

二、最終效果

vue+element-ui el-table組件二次封裝實現(xiàn)虛擬滾動,解決數(shù)據(jù)量大渲染DOM過多而卡頓問題,基于element和antd組件二次封裝,vue.js,el-table,elementui,二次封裝,虛擬列表,頁面卡頓,虛擬滾動

三、需求

某些頁面不做分頁時,當數(shù)據(jù)過多,會導(dǎo)致頁面卡頓,甚至卡死

四、虛擬滾動

一、固定一個可視區(qū)域的大小并且其大小是不變的,那么要做到性能最大化就需要盡量少地渲染 DOM 元素,而這個最小值也就是可視范圍內(nèi)需要展示的內(nèi)容,而可視區(qū)域之外的元素均可以不做渲染。
二、如何計算可視區(qū)域內(nèi)需要渲染的元素,我們通過如下幾步來實現(xiàn)虛擬滾動:

1、每一行的高度需要相同,方便計算。
2、需要知道渲染的數(shù)據(jù)量(數(shù)組長度),可基于總量和每個元素的高度計算出容器整體的所需高度,這樣就可以偽造一個真實的滾動條。
3、獲取可視區(qū)域的高度。
4、在滾動事件觸發(fā)后,滾動條的距頂距離即這個數(shù)據(jù)量中的偏移量,再根據(jù)可視區(qū)域本身的高度,算出本次偏移量,這樣就得到了需要渲染的具體數(shù)據(jù)

五、具體實現(xiàn)(源碼)

<template>
  <div class="t-table" id="t_table">
    <el-table
      ref="el-table"
      :data="tableData"
      :class="{
        cursor: isCopy,
        row_sort: isRowSort,
        highlightCurrentRow: highlightCurrentRow,
        radioStyle: table.firstColumn && table.firstColumn.type === 'radio',
        treeProps: isShowTreeStyle,
        is_sort_icon:onlyIconSort
      }"
      :max-height="useVirtual?maxHeight||540:maxHeight"
      v-bind="$attrs"
      v-on="$listeners"
      :highlight-current-row="highlightCurrentRow"
      :border="table.border || isTableBorder"
      :span-method="spanMethod || objectSpanMethod"
      :cell-class-name="cellClassNameFuc"
      @sort-change="soltHandle"
      @row-click="rowClick"
      @cell-dblclick="cellDblclick"
    >
      <!-- 主體內(nèi)容 -->
      <template v-for="(item, index) in renderColumns">
          <el-table-column
            v-if="item.isShowCol === false ? item.isShowCol : true"
            :key="index + 'i'"
            :type="item.type"
            :label="item.label"
            :prop="item.prop"
            :min-width="item['min-width'] || item.minWidth || item.width"
            :sortable="item.sort || sortable"
            :align="item.align || 'center'"
            :fixed="item.fixed"
            :show-overflow-tooltip="useVirtual?true:item.noShowTip?false:true"
            v-bind="{ ...item.bind, ...$attrs }"
            v-on="$listeners"
          >
            <template slot-scope="scope">
              ...
            </template>
          </el-table-column>
      </template>
    </el-table>
   </div>
</template>

<script>
export default {
  name: 'TTable',
  props: {
    // table所需數(shù)據(jù)
    table: {
      type: Object,
      default: () => {
        return {}
      }
      // required: true
    },
    // 表頭數(shù)據(jù)
    columns: {
      type: Array,
      default: () => {
        return []
      }
      // required: true
    },
    ...
    // Table最大高度
    maxHeight: {
      type: [String, Number]
    },
    // 是否開啟虛擬列表
    useVirtual: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      tableData: this.table?.data,
      /**
       * 虛擬列表
       */
      saveDATA: [], // 所有數(shù)據(jù)
      tableRef: null, // 設(shè)置了滾動的那個盒子
      tableWarp: null, // 被設(shè)置的transform元素
      fixLeft: null, // 固定左側(cè)--設(shè)置的transform元素
      fixRight: null, // 固定右側(cè)--設(shè)置的transform元素
      tableFixedLeft: null, // 左側(cè)固定列所在的盒子
      tableFixedRight: null, // 右側(cè)固定列所在的盒子
      scrollTop: 0,
      scrollNum: 0, // scrollTop / (itemHeight * pageList)
      start: 0,
      end: 30, // 3倍的pageList
      starts: 0, // 備份
      ends: 30, // 備份
      pageList: 10, // 一屏顯示
      itemHeight: 48 // 每一行高度
    }
  },
  watch: {
    'table.data': {
      handler(val) {
        if (this.useVirtual) {
          this.saveDATA = val
          this.tableData = this.saveDATA.slice(this.start, this.end)
        } else {
          this.tableData = val
        }
      },
      deep: true // 深度監(jiān)聽
    },
    scrollNum(newV) {
      // 因為初始化時已經(jīng)添加了3屏的數(shù)據(jù),所以只有當滾動到第3屏時才計算位移量
      if (newV > 1) {
        this.start = (newV - 1) * this.pageList
        this.end = (newV + 2) * this.pageList
        requestAnimationFrame(() => {
          // 計算偏移量
          this.tableWarp.style.transform = `translateY(${this.start *
            this.itemHeight}px)`
          if (this.fixLeft) {
            this.fixLeft.style.transform = `translateY(${this.start *
              this.itemHeight}px)`
          }
          if (this.fixRight) {
            this.fixRight.style.transform = `translateY(${this.start *
              this.itemHeight}px)`
          }
          this.tableData = this.saveDATA.slice(this.start, this.end)
        })
      } else {
        requestAnimationFrame(() => {
          this.tableData = this.saveDATA.slice(this.starts, this.ends)
          this.tableWarp.style.transform = `translateY(0px)`
          if (this.fixLeft) {
            this.fixLeft.style.transform = `translateY(0px)`
          }
          if (this.fixRight) {
            this.fixRight.style.transform = `translateY(0px)`
          }
        })
      }
    }
  },
  created() {
    // 是否開啟虛擬列表
    if (this.useVirtual) {
      this.init()
    }
  },
  mounted() {
    // 是否開啟虛擬列表
    if (this.useVirtual) {
      this.initMounted()
    }
  },
  methods: {
    initMounted() {
      this.$nextTick(() => {
        // 設(shè)置了滾動的盒子
        this.tableRef = this.$refs['el-table'].bodyWrapper
        // 左側(cè)固定列所在的盒子
        this.tableFixedLeft = document.querySelector(
          '.el-table .el-table__fixed .el-table__fixed-body-wrapper'
        )
        // 右側(cè)固定列所在的盒子
        this.tableFixedRight = document.querySelector(
          '.el-table .el-table__fixed-right .el-table__fixed-body-wrapper'
        )
        /**
         * fixed-left | 主體 | fixed-right
         */
        // 創(chuàng)建內(nèi)容盒子divWarpPar并且高度設(shè)置為所有數(shù)據(jù)所需要的總高度
        let divWarpPar = document.createElement('div')
        // 如果這里還沒獲取到saveDATA數(shù)據(jù)就渲染會導(dǎo)致內(nèi)容盒子高度為0,可以通過監(jiān)聽saveDATA的長度后再設(shè)置一次高度
        divWarpPar.style.height = this.saveDATA.length * this.itemHeight + 'px'
        // 新創(chuàng)建的盒子divWarpChild
        let divWarpChild = document.createElement('div')
        divWarpChild.className = 'fix-warp'
        // 把tableRef的第一個子元素移動到新創(chuàng)建的盒子divWarpChild中
        divWarpChild.append(this.tableRef.children[0])
        // 把divWarpChild添加到divWarpPar中,最把divWarpPar添加到tableRef中
        divWarpPar.append(divWarpChild)
        this.tableRef.append(divWarpPar)
        // left改造
        let divLeftPar = document.createElement('div')
        divLeftPar.style.height = this.saveDATA.length * this.itemHeight + 'px'
        let divLeftChild = document.createElement('div')
        divLeftChild.className = 'fix-left'
        this.tableFixedLeft &&
          divLeftChild.append(this.tableFixedLeft.children[0])
        divLeftPar.append(divLeftChild)
        this.tableFixedLeft && this.tableFixedLeft.append(divLeftPar)
        // right改造
        let divRightPar = document.createElement('div')
        divRightPar.style.height = this.saveDATA.length * this.itemHeight + 'px'
        let divRightChild = document.createElement('div')
        divRightChild.className = 'fix-right'
        this.tableFixedRight &&
          divRightChild.append(this.tableFixedRight.children[0])
        divRightPar.append(divRightChild)
        this.tableFixedRight && this.tableFixedRight.append(divRightPar)
        // 被設(shè)置的transform元素
        this.tableWarp = document.querySelector(
          '.el-table .el-table__body-wrapper .fix-warp'
        )
        this.fixLeft = document.querySelector(
          '.el-table .el-table__fixed .el-table__fixed-body-wrapper .fix-left'
        )
        this.fixRight = document.querySelector(
          '.el-table .el-table__fixed-right .el-table__fixed-body-wrapper .fix-right'
        )
        this.tableRef.addEventListener('scroll', this.onScroll)
      })
    },
    // 初始化數(shù)據(jù)
    init() {
      this.saveDATA = this.table?.data
      this.tableData = this.saveDATA.slice(this.start, this.end)
    },
    // 滾動事件
    onScroll() {
      this.scrollTop = this.tableRef.scrollTop
      this.scrollNum = Math.floor(this.scrollTop / (this.itemHeight * this.pageList))
    }
  }
}
</script>

六、源碼地址

GitHub源碼地址

Gitee源碼地址

基于ElementUi或Antd再次封裝基礎(chǔ)組件文檔

vue3+ts基于Element-plus再次封裝基礎(chǔ)組件文檔文章來源地址http://www.zghlxwxcb.cn/news/detail-695002.html

到了這里,關(guān)于vue+element-ui el-table組件二次封裝實現(xiàn)虛擬滾動,解決數(shù)據(jù)量大渲染DOM過多而卡頓問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包