搬运日记-table不分页情况下解决加载成千上万条数据不卡顿 vue+element-ui

500 阅读1分钟
固定渲染dom量,给表格固定高度,只渲染用户在表格中滚动的视图dom
<el-table
  v-loadmore="handelLoadmore      
  :data="filteredData"
  :data-size="tableDataList.length"
>
    <el-table-column prop="time" label="时间" align="center" />
    <el-table-column prop="equiName" label="设备" align="center" />
</el-table>
<script>
export default {
  data() {
    return {
      tableDataList: [],
      // 渲染21条数据
      currentStartIndex: 0,
      currentEndIndex: 20
    };
  },
  directives: {
    loadmore: {
      componentUpdated: function (el, binding, vnode, oldVnode) {
        // 设置默认溢出显示数量
        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
            );
          });
        };
        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);
          });
        });
      }
    }
  },
  computed: {
    filteredData() {
      let list = this.tableDataList.filter((item, index) => {
        if (index < this.currentStartIndex) {
          return false;
        } else if (index > this.currentEndIndex) {
          return false;
        } else {
          return true;
        }
      });
      return list;
    }
  },
  async mounted() {
    this.getTableData()
  },
  methods: {
    handelLoadmore(currentStartIndex, currentEndIndex) {
      this.currentStartIndex = currentStartIndex;
      this.currentEndIndex = currentEndIndex;
    },
    getTableData() {
    // 获取表格数据写这里
  }
};
</script>