处理el-table大数据卡顿的问题,包含tree型数据格式

这篇具有很好参考价值的文章主要介绍了处理el-table大数据卡顿的问题,包含tree型数据格式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概要

如果你有更丰富的表格需求,可以查看我另一篇文章 关于vxe-table的使用心得及扩展

1、现象
有时候el-table的数据可能有成千上万条,而且又要在一页显示完,这时候页面渲染的dom太多了,可能会造成页面卡顿。

解决方案:给表格固定高度,只渲染用户在表格中滚动的视图dom
2、卡顿原因
因为数据量过多导致浏览器渲染过多的标签元素 导致DOM树占用内存较大 使得用户操作阻塞。
具体原理可参考别的大佬写的文章:DOM性能瓶颈与Javascript性能优化.

3、解决方法及原理
原理
解决思路可参考: 页面中长列表滚动的优化.

解决方法
使用第三方插件 npmjs.com/package/pl-ta

技术细节

<template>
  <!-- 使用 useVirtual 属性开启虚拟滚动 使用虚拟滚动时,必须要固定表格高度和行高 -->
  <div style="height: 100%;width: 100%;padding: 0 30px">
    <div style="color:red;">pl-table在线预览,更多玩法请看文档哦,欢迎Star</div>
    <el-button @click="$router.push({ path: '/text' })"
      >去子页面(为了测试缓存组件)</el-button
    >
    <div>
      <el-button @click="allSelection">全选</el-button>
      <el-button @click="clearSelection">清除选中</el-button>
      <el-button @click="setData(3)">变化数据为3</el-button>
      <el-button @click="setData(200)">变化数据为200</el-button>
      <el-button @click="setData(1000)">变化数据为1000</el-button>
      <el-button @click="pagingScrollTopLeft(1000)">滚动到1千位置</el-button>
      <el-button @click="pagingScrollTopLeft(2000)">滚动到2千位置</el-button>
      <el-button @click="pagingScrollTopLeft(0)">滚动到顶部</el-button>
      <el-button @click="scrollBottom">滚动到底部位置</el-button>
      <el-button @click="setHei(400)">设置高度为400</el-button>
      <el-button @click="setHei(300)">设置高度为300</el-button>
    </div>
 
    <!--我是Y轴虚拟-->
    <div v-if="true">
      <p style="color: red">我是Y轴虚拟</p>
      <pl-table
        ref="plTable"
        :height="height"
        :data="data.tableData"
        selectTrClass="selectTr"
        header-drag-style
        :dataChangesScrollTop="false"
        :summary-method="summaryMethod"
        @table-body-scroll="tableBodyScroll"
        fixedColumnsRoll
        inverse-current-row
        bigDataCheckbox
        @select-all="selectAll"
        show-summary
        use-virtual
        :row-height="rowHeight"
      >
        <template slot="empty">
          没有查询到符合条件的记录
        </template>
        <pl-table-column type="selection" width="55" :selectable="selectable" />
        <pl-table-column type="index" width="100" fixed />
        <!--show-overflow-tooltip属性代表超出则内容部分给出提示框-->
        <pl-table-column
          v-for="item in columns"
          :key="item.id"
          :resizable="item.resizable"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :prop="item.prop"
          :label="item.label"
          :fixed="item.fixed"
          :width="item.width"
        />
      </pl-table>
    </div>
    <!--我是X + Y轴同时虚拟-->
    <div v-if="true">
      <p style="color: red">我是X + Y轴同时虚拟</p>
      <plx-table-grid
        :data="data.tableData"
        height="300"
        :show-summary="true"
        :summary-method="summaryMethod"
        ref="plTable2"
      >
        <plx-table-column type="selection" width="55" fixed="left" />
        <plx-table-column type="index" width="100" fixed="left" />
        <plx-table-column
          v-for="item in columns2"
          :key="item.id"
          :resizable="item.resizable"
          :prop="item.prop"
          :label="item.label"
          :fixed="item.fixed"
        />
      </plx-table-grid>
    </div>
 
    <!--我是加入分页的表格-->
    <div v-if="false">
      <p style="color: red">我是加入分页的表格</p>
      <pl-table
        :data="data.tableData"
        big-data-checkbox
        :max-height="height"
        header-drag-style
        fixedColumnsRoll
        use-virtual
        :row-height="rowHeight"
        :pagination-show="true"
        :total="pageForm.total"
        :page-size="pageForm.pageSize"
        :current-page="pageForm.currentPage"
        @handlePageSize="handlePageSize"
      >
        <template slot="empty">
          没有查询到符合条件的记录
        </template>
        <pl-table-column type="selection" width="55" />
        <pl-table-column type="index" width="100" fixed />
        <!--show-overflow-tooltip属性代表超出则内容部分给出提示框-->
        <pl-table-column
          v-for="item in columns"
          :key="item.id"
          :resizable="item.resizable"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :prop="item.prop"
          :label="item.label"
          :fixed="item.fixed"
          :width="item.width"
        />
      </pl-table>
    </div>
 
    <!--我是普通的el-table树形表格,这个数据多了就卡,这就是原本的el-table树表格,必须指定 row-key-->
    <div v-if="false">
      <p style="color: red;">
        我是普通的el-table树形表格,这个数据多了就卡,这就是原本的el-table树表格,必须指定
        row-key
      </p>
      <pl-table
        ref="plTable"
        :height="height"
        :data="treeData"
        selectTrClass="selectTr"
        row-key="id"
        header-drag-style
        @table-body-scroll="tableBodyScroll"
        fixedColumnsRoll
        inverse-current-row
        @select-all="selectAll"
      >
        <template slot="empty">
          没有查询到符合条件的记录
        </template>
        <!--show-overflow-tooltip属性代表超出则内容部分给出提示框-->
        <pl-table-column
          v-for="item in columns"
          :key="item.id"
          :resizable="item.resizable"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :prop="item.prop"
          :label="item.label"
          :fixed="item.fixed"
          :width="item.width"
        />
      </pl-table>
    </div>
 
    <!--我是pl-table大数据树形表格 必须指定 row-key  必须开启use-virtual-->
    <div v-if="true">
      <p style="color: red;">
        我是pl-table大数据树形表格 必须指定 row-key 必须开启use-virtual
      </p>
      <el-button @click="$refs.plTreeTable.toggleTreeExpansion(treeData[0])"
        >切换第一个</el-button
      >
      <el-button @click="$refs.plTreeTable.setTreeExpansion(treeData[2], true)"
        >展开第三个</el-button
      >
      <el-button @click="$refs.plTreeTable.setAllTreeExpansion()"
        >展开全部</el-button
      >
      <el-button @click="$refs.plTreeTable.clearTreeExpand()"
        >关闭所有</el-button
      >
      <el-button @click="getTreeExpansionEvent">获取已展开</el-button>
      <pl-table
        ref="plTreeTable"
        :max-height="height"
        :data="treeData"
        selectTrClass="selectTr"
        row-key="id"
        bigDataCheckbox
        :treeConfig="{ children: 'children', expandAll: false }"
        :use-virtual="true"
        header-drag-style
        @table-body-scroll="tableBodyScroll"
        fixedColumnsRoll
        inverse-current-row
        @select-all="selectAll"
      >
        <template slot="empty">
          没有查询到符合条件的记录
        </template>
        <!--pl-table大数据表格 你需要在列上指定某个列显示展开收起 treeNode属性-->
        <pl-table-column
          :treeNode="item.treeNode"
          v-for="item in columns"
          :key="item.id"
          :resizable="item.resizable"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :prop="item.prop"
          :label="item.label"
          :fixed="item.fixed"
          :width="item.width"
        />
      </pl-table>
    </div>
  </div>
</template>
 
<script>
// 下面是关于pl-table的树形数据的介绍,希望读完下面的文字
 
// (最大数量500)当然你可以更多,那么只会导致你遍历时间多,页面等待时间长,(并非渲染节点时间长)
// 另外 就以下的这个层级,总数据量展开后,就是 500 + 500 x 3 + 3 x 1 = 2003 的总数据量
// 如果你 第一级是500, 第二级也是500, 第三级是10。那么你的数据量就是 500 + 500 x 500 + 500 x 10 的总数据量,这是非常吓人的
// 所以结合自己情况去给树数据,不要瞎乱给下面的数据,树节点避免不鸟去递归,如果你的数据量很大很大,那么你会死在遍历上。
// 注意,注意,注意:并非第一级不能超过500,是想告诉你们嵌套里面子节点层级数据量不要太大。比如你可这样的:第一级为1000, 第二级为2-5的数据量,
// 第三级为2-5的数据量...., 那么这样算下来,就是 1000 + 1000 x 5  + 5 x 5  = 6025的数据量,应该是可以的,但是记住要是太大的嵌套数据。那只会导致
// 程序卡在遍历数据上,因为程序需要慢慢去递归遍历。这是没有办法的。
 
// 但是传统el-table  或者el-tree他们数据量超过200  就会卡。所以我们已经很好的优化了这一点。不过看来对于树形数据的要求,应该数据量不会太大。
// 你可以在pl-table的基础上去改改样式,就可以变相的去实现el-tree的组件了哦,你隐藏下头部,把行的高度给小一点。然后隐形边框线。是不是就是el-tree了呢???
 
var dataList = Array.from({ length: 500 }, (_, idx) => ({
  id: idx + "_" + 1,
  date: "2016-05-03",
  name: 1,
  ab: "欢迎使用pl-table",
  address: idx,
  children: Array.from({ length: 3 }, (_, idx2) => ({
    id: idx + "_" + idx2 + "_" + 1,
    date: "2016-05-03",
    name: 1,
    ab: "欢迎使用pl-table",
    address: idx + "_" + idx2,
    children: Array.from({ length: 1 }, (_, idx3) => ({
      id: idx + "_" + idx2 + "_" + idx3 + "_" + 1,
      date: "2016-05-03",
      name: 1,
      ab: "欢迎使用pl-table",
      address: idx + "_" + idx2 + "_" + idx3
    }))
  }))
}));
export default {
  name: "home",
  data() {
    return {
      rowHeight: 50,
      columns: [
        {
          prop: "address",
          label: "日期",
          width: 120,
          treeNode: true,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "地址",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "噜噜噜",
          width: 230,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "地址",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "地址",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true
        },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true
        },
        { prop: "address", label: "噜噜噜", showOverflowTooltip: true },
        {
          prop: "address",
          label: "娃哈哈",
          width: 100,
          showOverflowTooltip: true,
          fixed: "right"
        }
      ],
      columns2: Array.from({ length: 20 }, (_, idx) => ({
        prop: "address",
        label: "地址" + idx,
        width: 200,
        showOverflow: true,
        sortable: true,
        fixed: ""
      })),
      data: {
        tableData: Array.from({ length: 10000 }, (_, idx) => ({
          id: idx + 1,
          date: "2016-05-03",
          name: 1,
          ab: "欢迎使用pl-table",
          address: 1 + idx
        }))
      },
      top: 0,
      height: 500,
      pageForm: {
        total: 1000,
        pageSize: 10,
        currentPage: 1
      },
      treeData: dataList
    };
  },
  methods: {
    selectAll(val) {
      console.log(val);
    },
    selectable(row, index) {
       
      if (index === 1) {
        return false;
      } else {
        console.log(row,index);
 
        return true;
      }
    },
    // 合计
    summaryMethod({ columns, data }) {
      // 平均值算法(不需要自己去掉)
      function cacl(arr, callback) {
        let ret;
        for (let i = 0; i < arr.length; i++) {
          ret = callback(arr[i], ret);
        }
        return ret;
      }
      // 平均值算法(不需要自己去掉)
      Array.prototype.sum = function() {
        return cacl(this, function(item, sum) {
          if (typeof sum == "undefined") {
            return item;
          } else {
            return (sum += item);
          }
        });
      };
      // 平均值算法(不需要自己去掉)
      Array.prototype.avg = function() {
        if (this.length == 0) {
          return 0;
        }
        return this.sum(this) / this.length;
      };
      const means = []; // 合计
      const fenceSums = []; // 平均值
      columns.forEach((column, columnIndex) => {
        if (columnIndex === 0) {
          means.push("合计");
          fenceSums.push("平均值");
        } else {
          const values = data.map(item => Number(item[column.property]));
          // 合计
          if (!values.every(value => isNaN(value))) {
            means[columnIndex] = values.reduce((prev, curr) => {
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
            // means[columnIndex] += ' 元'
            // 改变了ele的合计方式,扩展了合计场景
            // 你以为就只有上面这样玩吗?错啦,你还可以自定义样式哦
            // means[columnIndex] = '<span style="color: red">' + means[columnIndex] + '元</span>'
            means[columnIndex] =
              '<span style="color: red">' +
              means[columnIndex] +
              "元</span><br/><span>123</span>";
          } else {
            means[columnIndex] = "";
          }
          // 平均值
          const precisions = [];
          let notNumber = true;
          values.forEach(value => {
            if (!isNaN(value)) {
              notNumber = false;
              let decimal = ("" + value).split(".")[1];
              precisions.push(decimal ? decimal.length : 0);
            }
          });
          if (!notNumber) {
            fenceSums[columnIndex] = values.avg();
          } else {
            fenceSums[columnIndex] = "";
          }
        }
      });
      // 返回一个二维数组的表尾合计
      return [means, fenceSums];
    },
    setHei(val) {
      this.height = val;
    },
    tableBodyScroll({ scrollTop }) {
      this.top = scrollTop;
    },
    allSelection() {
      this.$refs.plTable.toggleAllSelection();
    },
    clearSelection() {
      this.$refs.plTable.clearSelection();
      this.$refs.plTable2.clearSelection();
    },
    setData(num) {
      this.data.tableData = Array.from({ length: num }, (_, idx) => ({
        id: idx + 1,
        date: "2016-05-03",
        name: 1,
        ab: "欢迎使用pl-table",
        address: 1 + idx
      }));
    },
    scrollBottom() {
      this.$refs.plTable.scrollBottom();
    },
    pagingScrollTopLeft(val) {
      this.$refs.plTable.pagingScrollTopLeft(val, 0);
    },
    // 分页事件
    handlePageSize({ page, size }) {
      console.log(page, size);
    },
    // 获取已经展开的节点
    getTreeExpansionEvent() {
      console.log(this.$refs.plTreeTable.getTreeExpandRecords());
    }
  }
};
</script>
<style>
body,
html {
  margin: 0;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
}
body ::-webkit-scrollbar-thumb {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  background-color: rgba(144, 147, 153, 0.5);
}
.selectTr td {
  background: #ccc !important;
  color: red !important;
}
</style>

小结

此搬运是为了防止地址失效,原作者在下方

感谢原文地址文章来源地址https://www.toymoban.com/news/detail-720361.html

到了这里,关于处理el-table大数据卡顿的问题,包含tree型数据格式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue Element UI 中 el-table 树形数据 tree-props 多层级使用避坑

    实现效果: element官网提示设置tree-props为{children: ‘children’,hasChildren: ‘hasChildren’},data数据需要设置children和hasChildren属性,row-key也绑定了数据的唯一值变量id,但是 树形结构的第三级就是出不来 可以看到只有第二级,第三级并没有,于是查看了 数据格式 ,和官方要求的

    2024年02月02日
    浏览(84)
  • el-table 设置行背景颜色 鼠标移入高亮问题处理

    后端返回表格数据,有特定行数需要用颜色标识。类似于以下需求: 方式 区别 :row-class-name=“tableRowClassName” 已返回类名的形式设置样式,代码整洁,但是会鼠标高亮,导致背景颜色失效 :cell-style=“cellStyle” 以返回样式的形式设置,无鼠标高亮问题 2.1 表格代码 2.2 :row-cla

    2024年02月15日
    浏览(55)
  • 将较大的数组赋值<el-table></el-table>时,会导致页面卡顿,甚至崩溃

    遇到的问题:将长度为40的数组数据赋值el-table/el-table,我发现loading没有效果,后面发现是页面卡住了,loading直接没有出现。 经过查询资料,发现el-table会有卡顿的问题,看到有的博主推荐使用一款叫umy-ui的插件,我就试了试,发现卡顿的问题解决了。 官网: http://www.umyui

    2024年02月05日
    浏览(62)
  • el-table不显示数据的问题

    最近调试用element-ui中的el-table来显示数据,发现无法显示出数据,通过调试,发现后台的数据传到前台了。如图所示:  从网上收集到两种答案都不成功。一种是将element-ui的版本降级。一种是在webpack里面设置一下:vue: \\\'vue/dist/vue.esm.js\\\',原因是说element-ui使用的Vue版本与当前的

    2024年02月11日
    浏览(38)
  • 【elementplus】解决el-table使用el-popconfirm,只剩下一行数据时,popconfirm提示框会被el-table边框遮挡的问题

    首先,先通过以下链接的方法,解决 在el-table中使用popconfirm、popover、tooltip、select时,出现placement错位或者框被table的列遮挡的问题 然后就是有可能会出现 el-table只剩下一行数据,popconfirm提示框依旧会被el-table边框遮挡的问题 解决方案: 给el-table设置固定高度,通常我会给

    2024年02月12日
    浏览(41)
  • el-table 多表格弹窗嵌套数据显示异常错乱问题

    使用vue+element开发报表功能时,需要列表上某列的超链接按钮弹窗展示,在弹窗的el-table列表某列中再次使用超链接按钮点开弹窗,以此类推多表格弹窗嵌套,本文以弹窗两次为例 最终效果如下示例页面 这里有几个可能的原因和建议来解决这个问题: ①数据问题: 首先确保

    2024年02月05日
    浏览(46)
  • vue 解决el-table 表体数据发生变化时,未重新渲染问题

     父组件中数量改变后总数重新计算 父组件代码  WmsTable 是子组件名  WmsTable 中的数量字段quantity修改时重新计算合计

    2024年01月20日
    浏览(35)
  • 解决el-table组件中,分页后数据的勾选、回显问题?

    问题描述:         1、记录一个弹窗点击确定按钮后,table列表所有勾选的数据信息         2、再次打开弹窗,回显勾选所有保存的数据信息         3、遇到的bug:切换分页,其他页面勾选的数据丢失;点击确认只保存当前页的数据;勾选数据保存后但并未回显

    2024年02月08日
    浏览(102)
  • 【ElementUI】el-table中复选框禁用处理

    Vue 项目开发过程中,尤其是后台管理开发,经常会用到 ElementUI 中的表格和表单,有时候我们需要在表格中添加复选框,来实现全选和单选当前行的操作,而这时如果有条件要限制选框是否禁用该如何处理呢?这就需要展开来说了,因为表头全选和表格行中的单个选择处理是

    2024年02月07日
    浏览(37)
  • el-table 固定列错位的问题

    问题描述 给el-table表个的操作列设置了固定,即fixed:right,出现了操作列高度与其他列高度不统一 ,导致行错位的情况,如下图: 并且即便重新渲染表格,也无法解决该问题 问题分析 1.将出操作列以外的其他列的代码都注释,会看到表格变成下图: 可以看到左侧一列没有

    2024年02月15日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包