1、现象
有时候el-table的数据可能有成千上万条,而且又要在一页显示完,这时候页面渲染的dom太多了,可能会造成页面卡顿。
解决方案:给表格固定高度,只渲染用户在表格中滚动的视图dom
2、卡顿原因
因为数据量过多导致浏览器渲染过多的标签元素 导致DOM树占用内存较大 使得用户操作阻塞。
具体原理可参考别的大佬写的文章: DOM性能瓶颈与Javascript性能优化.
3、解决方法及原理
原理
解决思路可参考: 页面中长列表滚动的优化.
解决方法
使用第三方插件 www.npmjs.com/package/pl-…\
<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>
今天的文章el-table大数据量渲染卡顿的解决方案分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/17796.html