elementui表格性能优化123
最近公司需要使⽤vue重构以前的项⽬,为了节省时间快速开发选择了使⽤element
不得不说,咋⼀看element的功能很全⾯样式,该有的都⽤,但是我们的项⽬对性能要求⽐较⾼,特别是表格
开发过程⽐较顺利各功能实现都很不难,但是性能测试确成了问题,分页的情况下单页100条就不怎么流畅了,更别说要求不分页5000条,直接加载过程中内存爆掉卡死了,于是开始了分析源码的路;
到element/packages/table/src表格的代码都在这⾥
⼊⼝是table.vue  我们要看的是具体数据⽣成部分看名字就知道是table-body.js
点进去⼀看,你基本就知道性能慢是个什么情况了,整体使⽤vue的render⽅法⽣成整个界⾯,整个table部分
render(h) {
const columnsHidden = lumns.map((column, index) => this.isColumnHidden(index));
return (
<table
class="el-table__body"
cellspacing="0"
cellpadding="0"
border="0">
<colgroup>
{
this._lumns, column => <col name={ column.id } />)
}
</colgroup>
<tbody>
{
this._l(this.data, (row, $index) =>
[<tr
style={ wStyle ? RowStyle(row, $index) : null }
key={ wKey ? KeyOfRow(row, $index) : $index }
on-dblclick={ ($event) => this.handleDoubleClick($event, row) }
on-click={ ($event) => this.handleClick($event, row) }
on-contextmenu={ ($event) => this.handleContextMenu($event, row) }
on-mouseenter={ _ => this.handleMouseEnter($index) }
on-mouseleave={ _ => this.handleMouseLeave() }
class={ [RowClass(row, $index)] }>
{
this._lumns, (column, cellIndex) => {
const { rowspan, colspan } = Span(row, column, $index, cellIndex);
if (!rowspan || !colspan) {
return '';
} else {
if (rowspan === 1 && colspan === 1) {
return (
<td
style={ CellStyle($index, cellIndex, row, column) }
class={ CellClass($index, cellIndex, row, column) }
on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) }
on-mouseleave={ this.handleCellMouseLeave }>
{
this._renderProxy,
h,
{
row,
column,
$index,
store: this.store,
_self: t || this.table.$t
},
columnsHidden[cellIndex]
)
}
</td>
);
} else {
return (
<td
style={ CellStyle($index, cellIndex, row, column) }
class={ CellClass($index, cellIndex, row, column) }
rowspan={ rowspan }
colspan={ colspan }
on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) }
on-mouseleave={ this.handleCellMouseLeave }>
{
this._renderProxy,
h,
{
row,
column,
$index,
store: this.store,
_self: t || this.table.$t
},
columnsHidden[cellIndex]
)
}
</td>
);
}
}
})
}
</tr>,
this.store.isRowExpanded(row)
? (<tr>
<td colspan={ lumns.length } class="el-table__expanded-cell">
{ derExpanded ? derExpanded(h, { row, $index, store: this.store }) : ''}
</td>
</tr>)
:
''
]
).concat(
<el-tooltip effect={ ltipEffect } placement="top" ref="tooltip" content={ ltipContent }></el-tooltip> )
}
</tbody>
</table>
);
},
},
我不太清楚render⽣成界⾯的时候是否会在数据变更后整体重新渲染界⾯,就算不会也会有⼀个变更判断过程,⽽他是实实在在的重新⽣成了整个table的vnode对象,还包含⼀堆⼦集,然后返回渲染,这个过程感觉不会快,特别是数据量⼤的时候
中间的思考过程略过,对⽐了vue的另⼀款table控件的源代码vue-easytable并试验了他的性能,决定第⼀步就是将界⾯⽣成⽅式改为template,并且将点击事件进⾏了委托
别的就不说了上代码
<template>
<table
class="el-table__body"
cellspacing="0"
cellpadding="0"
border="0">
<colgroup>
<col v-for="col in columns"
:key="col.id"
:name="col.id"
:width="col.width"/>
</colgroup>
<tbody
@click="handleClick"
@dblclick="handleDoubleClick"
@contextmenu="handleContextMenu">
<tr v-for="(row,$index) in data"
:
:key="trKey(row, $index)"
@mouseenter="handleMouseEnter($index)"
@mouseleave="handleMouseLeave"
:class="trClass(row, $index)"
:index="$index">
<td v-for="(column,cellIndex) in columns"
v-if="getSpan(row, column, $index, cellIndex)"
:
:class="getCellClass($index, cellIndex, row, column)"
:rowspan="column._rowspan"
:
colspan="column._colspan"
@mouseenter="handleCellMouseEnter($event, row)"
@mouseleave="handleCellMouseLeave">
到这⾥问题就来了,他的⽣成调⽤了其他⽂件⾥的⽅法table-column.js,⽔平有限学vue也没多久,他这个将具体的内容填充⽣成的⽅式没看懂,也没太多时间去研究
这个时候有两个思路
1.继续沿⽤他render的⽣成⽅式,我是重新写了⼀个⼩组件,在这个组件⾥去使⽤render⽣成就⾏,如下所⽰
<ElTableCell
:store="store"
:config="config(row,column,$index)"></ElTableCell>vue element admin
2.牺牲他的灵活性,根据你具体的需求在这⾥⼿动判断⽣成想要的界⾯,你只需要把配置数据传递过
来就⾏,这样做对性能提升是巨⼤的,正如 vue-easytable的编辑模式⼀样,模式少的可怜,这样也最快
如果你有多个编辑模式什么的,最好使⽤v-if,不要⽤v-show,可以⼤⼤提升加载速度,如下所⽰
<div v-else class="cell">
<div v-else-if="realtype(column)=='input'">
<div v-if="isHide(row)">{{row[column.keys]}}</div>
<el-input
v-else
type="input"
size="mini"
v-show="row.edit"
v-model="row[column.keys]">
</el-input>
</div>
<div v-else>
{{row[column.keys]}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</template>
经测试第⼀种ElTableCell的⽅式有⼀定的性能提升⼏百条应该没什么问题,不⾄于100就卡,但是1000条就会偶尔内存爆掉,单击双击编辑模式什么的速度提升⽐较明显;
第⼆种⾃定义模板的⽅式提升就⽐较⼤了,5000条没有问题,但是各种操作相对于第⼀种会慢不少,不过需要传递过来配置数据
这两种⽅式在数据量少的时候流畅度提升巨⼤,特别是⼏百条的时候感觉⽐较明显
原始⽣产⽅式的最后⼀段代码,tr⽣成的是展开⾏的具体内容(我不需要就没加),下⾯的是tooltip提⽰,暂时来说还不需要
this.store.isRowExpanded(row)
? (<tr>
<td colspan={ lumns.length } class="el-table__expanded-cell">
{ derExpanded ? derExpanded(h, { row, $index, store: this.store }) : ''}
</td>
</tr>)
: ''
]
).concat(
<el-tooltip effect={ ltipEffect } placement="top" ref="tooltip" content={ ltipContent }></el-
tooltip>
)
两种⽅式均需要再下⾯添加⼀些属性和⽅法,这⾥就不具体说明了,⾃⼰看
。。。有好的⽅式,可以教教我,感谢

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。