关于处理万级数据编辑表格的踩坑日志
1、简介:项目需求要弄一个数据录入表格,数据比较多并且是可编辑,按键切换输入框,左侧固定列等等,一开始表格是直接用的element,用着用着已经不满足需求,编辑数据多的时候慢的不行编辑还卡顿。
2、解决经历:一开始是打算用patch-package修改element源码的,然后发现引入的element引用的是打包后的lib,要改的话需要下载源码修改还要打包设置一个文件并修改引用路径,不然别人拉代码并不会拉到你改过的element,十分麻烦,后来找到了用Vue自定义指令不修改依赖来给element表格打补丁,试过之后发现不行还是很卡顿,之后又找到了umyui表格,说是可以处理万级数据,试了一下感觉还不错,算是不错的解决方案,于是记录一下
2-1、Vue自定义指令修改element渲染的方式(思路是表格只渲染固定的dom,滚动滚动条的时候切换dom的内容)
来源 https://segmentfault.com/q/1010000017202682
作者 Hally
新建一个loadmore.js文件
// 设置默认溢出显示数量 var spillDataNum = 20; // 设置隐藏函数 var timeout = false; let setRowDisableNone = function (topNum, showRowNum, binding) { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { binding.value.call(null, topNum, topNum + showRowNum + spillDataNum); }); }; export default { name: 'loadmore', componentUpdated: function (el, binding, vnode, oldVnode) { setTimeout(() => { const dataSize = vnode.data.attrs['data-size']; const oldDataSize = oldVnode.data.attrs['data-size']; if(dataSize === oldDataSize){ return; } const selectWrap = el.querySelector('.el-table__body-wrapper'); const selectTbody = selectWrap.querySelector('table tbody'); const selectRow = selectWrap.querySelector('table tr'); if (!selectRow) { return; } const rowHeight = selectRow.clientHeight; let showRowNum = Math.round(selectWrap.clientHeight / rowHeight); const createElementTR = document.createElement('tr'); let createElementTRHeight = (dataSize - showRowNum - spillDataNum) * rowHeight; createElementTR.setAttribute('style', `height: ${createElementTRHeight}px;`); selectTbody.append(createElementTR); // 监听滚动后事件 selectWrap.addEventListener('scroll', function () { let topPx = this.scrollTop - spillDataNum * rowHeight; let topNum = Math.round(topPx / rowHeight); let minTopNum = dataSize - spillDataNum - showRowNum; if (topNum > minTopNum) { topNum = minTopNum; } if (topNum < 0) { topNum = 0; topPx = 0; } selectTbody.setAttribute('style', `transform: translateY(${topPx}px)`); createElementTR.setAttribute('style', `height: ${createElementTRHeight-topPx > 0 ? createElementTRHeight-topPx : 0}px;`); setRowDisableNone(topNum, showRowNum, binding); }) }); } };
在main.js里面引入
import loadmore from '@/js/loadmore'
Vue.directive(loadmore.name,loadmore.componentUpdated);
然后在页面使用
<template>
  <div>
    <el-table border :data="filteredData" style="width: 100%" height="300" :data-size="tableData.length" v-loadmore="handelLoadmore">
      <el-table-column type="selection" width="55">
      </el-table-column>
      <el-table-column label="日期" width="180">
        <template slot-scope="scope">
          <div>
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{{ scope.row.date }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="日期" width="180">
        <template slot-scope="scope">
          <div>
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{{ scope.row.date }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="日期" width="180">
        <template slot-scope="scope">
          <div>
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{{ scope.row.date }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="日期" width="180">
        <template slot-scope="scope">
          <div>
            <i class="el-icon-time"></i>
            <span style="margin-left: 10px">{{ scope.row.date }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="姓名" width="180">
        <template slot-scope="scope">
          <div>
            <el-popover trigger="hover" placement="top">
              <p>姓名: {{ scope.row.name }}</p>
              <p>住址: {{ scope.row.address }}</p>
              <div slot="reference" class="name-wrapper">
                <el-tag size="medium">{{ scope.row.name }}</el-tag>
              </div>
            </el-popover>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <div>
            <el-button size="mini"  @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <el-button size="mini" type="danger"  @click="handleDelete(scope.$index, scope.row)">删除</el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  name: 'test',
  components: {},
  data () {
    return {
      tableData: [],
      currentStartIndex: 0,
      currentEndIndex: 20
    };
  },
  created () {
    this.getTableData();
  },
  computed: {
    filteredData () {
      return this.tableData.filter((item, index) => {
        if (index < this.currentStartIndex) {
          return false;
        } else if (index > this.currentEndIndex) {
          return false;
        } else {
          return true;
        }
      });
    }
  },
  methods: {
    handelLoadmore (currentStartIndex, currentEndIndex) {
      this.currentStartIndex = currentStartIndex;
      this.currentEndIndex = currentEndIndex;
    },
    getTableData () {
      let cont = 0;
      let tableData = [];
      while (cont < 30000) {
        cont = cont + 1;
        let object = {
          date: cont,
          name: '王小虎' + cont,
          address: '上海市普陀区金沙江路 cont 弄'
        }
        tableData.push(object);
      }
      setTimeout(() => {
        this.tableData = tableData;
      }, 2000);
    }
  },
  watch: {}
}
</script>
<style scoped>
.el-table__body-wrapper .el-table__row td {
  display: none;
}
.el-table__body-wrapper .el-table__row {
  height: 38px;
}
</style>
2-2、umy-ui表格(有很详细的文档)
官网:http://www.umyui.com/
github:https://github.com/u-leo/umy-ui

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号