处理el-table大数据卡顿的问题,包含tree型数据格式
•
大数据
文章目录
-
- 概要
- 技术细节
- 小结
概要
如果你有更丰富的表格需求,可以查看我另一篇文章 关于vxe-table的使用心得及扩展
1、现象
有时候el-table的数据可能有成千上万条,而且又要在一页显示完,这时候页面渲染的dom太多了,可能会造成页面卡顿。
解决方案:给表格固定高度,只渲染用户在表格中滚动的视图dom
2、卡顿原因
因为数据量过多导致浏览器渲染过多的标签元素 导致DOM树占用内存较大 使得用户操作阻塞。
具体原理可参考别的大佬写的文章:DOM性能瓶颈与Javascript性能优化.
3、解决方法及原理
原理
解决思路可参考: 页面中长列表滚动的优化.
解决方法
使用第三方插件 npmjs.com/package/pl-ta
技术细节
pl-table在线预览,更多玩法请看文档哦,欢迎Star
去子页面(为了测试缓存组件)
全选
清除选中
变化数据为3条
变化数据为200条
变化数据为1000条
滚动到1千位置
滚动到2千位置
滚动到顶部
滚动到底部位置
设置高度为400
设置高度为300
我是Y轴虚拟
没有查询到符合条件的记录
我是X + Y轴同时虚拟
我是加入分页的表格
没有查询到符合条件的记录
我是普通的el-table树形表格,这个数据多了就卡,这就是原本的el-table树表格,必须指定 row-key
没有查询到符合条件的记录
我是pl-table大数据树形表格 必须指定 row-key 必须开启use-virtual
切换第一个
展开第三个
展开全部
关闭所有
获取已展开
没有查询到符合条件的记录
// 下面是关于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] = '' + means[columnIndex] + '元'
means[columnIndex] =
'' +
means[columnIndex] +
"元
123";
} 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());
}
}
};
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;
}
小结
此搬运是为了防止地址失效,原作者在下方
感谢原文地址
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/6787848180.html
