Table: improve performance in large data. (#1298)

pull/1312/head
FuryBean 2016-11-23 18:24:32 +08:00 committed by cinwell.li
parent e3ac607938
commit 631037c296
7 changed files with 53 additions and 31 deletions

View File

@ -1,4 +1,4 @@
import { getValueByPath, getCell, getColumnByCell, getRowIdentity } from './util'; import { getCell, getColumnByCell, getRowIdentity } from './util';
export default { export default {
props: { props: {
@ -15,6 +15,7 @@ export default {
}, },
render(h) { render(h) {
const columnsHidden = this.columns.map((column, index) => this.isColumnHidden(index));
return ( return (
<table <table
class="el-table__body" class="el-table__body"
@ -40,7 +41,7 @@ export default {
{ {
this._l(this.columns, (column, cellIndex) => this._l(this.columns, (column, cellIndex) =>
<td <td
class={ [column.id, column.align, column.className || '', this.isCellHidden(cellIndex) ? 'is-hidden' : '' ] } class={ [column.id, column.align, column.className || '', columnsHidden[cellIndex] ? 'is-hidden' : '' ] }
on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) } on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) }
on-mouseleave={ this.handleCellMouseLeave }> on-mouseleave={ this.handleCellMouseLeave }>
{ {
@ -62,9 +63,10 @@ export default {
watch: { watch: {
'store.states.hoverRow'(newVal, oldVal) { 'store.states.hoverRow'(newVal, oldVal) {
if (!this.store.states.isComplex) return;
const el = this.$el; const el = this.$el;
if (!el) return; if (!el) return;
const rows = el.querySelectorAll('tr'); const rows = el.querySelectorAll('tbody > tr');
const oldRow = rows[oldVal]; const oldRow = rows[oldVal];
const newRow = rows[newVal]; const newRow = rows[newVal];
if (oldRow) { if (oldRow) {
@ -79,7 +81,7 @@ export default {
const el = this.$el; const el = this.$el;
if (!el) return; if (!el) return;
const data = this.store.states.data; const data = this.store.states.data;
const rows = el.querySelectorAll('tr'); const rows = el.querySelectorAll('tbody > tr');
const oldRow = rows[data.indexOf(oldVal)]; const oldRow = rows[data.indexOf(oldVal)];
const newRow = rows[data.indexOf(newVal)]; const newRow = rows[data.indexOf(newVal)];
if (oldRow) { if (oldRow) {
@ -128,7 +130,7 @@ export default {
return index; return index;
}, },
isCellHidden(index) { isColumnHidden(index) {
if (this.fixed === true || this.fixed === 'left') { if (this.fixed === true || this.fixed === 'left') {
return index >= this.leftFixedCount; return index >= this.leftFixedCount;
} else if (this.fixed === 'right') { } else if (this.fixed === 'right') {
@ -197,18 +199,6 @@ export default {
this.store.commit('setCurrentRow', row); this.store.commit('setCurrentRow', row);
table.$emit('row-click', row, event); table.$emit('row-click', row, event);
},
getCellContent(row, property, column) {
if (column && column.formatter) {
return column.formatter(row, column);
}
if (property && property.indexOf('.') === -1) {
return row[property];
}
return getValueByPath(row, property);
} }
} }
}; };

View File

@ -1,6 +1,7 @@
import ElCheckbox from 'element-ui/packages/checkbox'; import ElCheckbox from 'element-ui/packages/checkbox';
import ElTag from 'element-ui/packages/tag'; import ElTag from 'element-ui/packages/tag';
import objectAssign from 'element-ui/src/utils/merge'; import objectAssign from 'element-ui/src/utils/merge';
import { getValueByPath } from './util';
let columnIdSeed = 1; let columnIdSeed = 1;
@ -72,8 +73,17 @@ const getDefaultColumn = function(type, options) {
return column; return column;
}; };
const DEFAULT_RENDER_CELL = function(h, { row, column }, parent) { const DEFAULT_RENDER_CELL = function(h, { row, column }) {
return parent.getCellContent(row, column.property, column); const property = column.property;
if (column && column.formatter) {
return column.formatter(row, column);
}
if (property && property.indexOf('.') === -1) {
return row[property];
}
return getValueByPath(row, property);
}; };
export default { export default {
@ -182,7 +192,7 @@ export default {
className: this.className, className: this.className,
property: this.prop || this.property, property: this.prop || this.property,
type, type,
renderCell: DEFAULT_RENDER_CELL, renderCell: null,
renderHeader: this.renderHeader, renderHeader: this.renderHeader,
minWidth, minWidth,
width, width,
@ -229,15 +239,19 @@ export default {
}; };
} }
if (!renderCell) {
renderCell = DEFAULT_RENDER_CELL;
}
return _self.showOverflowTooltip || _self.showTooltipWhenOverflow return _self.showOverflowTooltip || _self.showTooltipWhenOverflow
? <el-tooltip ? <el-tooltip
effect={ this.effect } effect={ this.effect }
placement="top" placement="top"
disabled={ this.tooltipDisabled }> disabled={ this.tooltipDisabled }>
<div class="cell">{ renderCell(h, data, this._renderProxy) }</div> <div class="cell">{ renderCell(h, data) }</div>
<span slot="content">{ renderCell(h, data, this._renderProxy) }</span> <span slot="content">{ renderCell(h, data) }</span>
</el-tooltip> </el-tooltip>
: <div class="cell">{ renderCell(h, data, this._renderProxy) }</div>; : <div class="cell">{ renderCell(h, data) }</div>;
}; };
this.columnConfig = column; this.columnConfig = column;

View File

@ -42,6 +42,8 @@ class TableLayout {
} }
updateScrollY() { updateScrollY() {
const height = this.height;
if (typeof height !== 'string' || typeof height !== 'number') return;
const bodyWrapper = this.table.$refs.bodyWrapper; const bodyWrapper = this.table.$refs.bodyWrapper;
if (this.table.$el && bodyWrapper) { if (this.table.$el && bodyWrapper) {
const body = bodyWrapper.querySelector('.el-table__body'); const body = bodyWrapper.querySelector('.el-table__body');

View File

@ -55,6 +55,7 @@ const TableStore = function(table, initialState = {}) {
columns: [], columns: [],
fixedColumns: [], fixedColumns: [],
rightFixedColumns: [], rightFixedColumns: [],
isComplex: false,
_data: null, _data: null,
filteredData: null, filteredData: null,
data: null, data: null,
@ -246,6 +247,7 @@ TableStore.prototype.updateColumns = function() {
states.fixedColumns.unshift(_columns[0]); states.fixedColumns.unshift(_columns[0]);
} }
states.columns = [].concat(states.fixedColumns).concat(_columns.filter((column) => !column.fixed)).concat(states.rightFixedColumns); states.columns = [].concat(states.fixedColumns).concat(_columns.filter((column) => !column.fixed)).concat(states.rightFixedColumns);
states.isComplex = states.fixedColumns.length > 0 || states.rightFixedColumns.length > 0;
}; };
TableStore.prototype.isSelected = function(row) { TableStore.prototype.isSelected = function(row) {

View File

@ -1,6 +1,12 @@
<template> <template>
<div class="el-table" <div class="el-table"
:class="{ 'el-table--fit': fit, 'el-table--striped': stripe, 'el-table--border': border }" :class="{
'el-table--fit': fit,
'el-table--striped': stripe,
'el-table--border': border,
'el-table--enable-row-hover': !store.states.isComplex,
'el-table--enable-row-transition': true || (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
}"
@mouseleave="handleMouseLeave($event)"> @mouseleave="handleMouseLeave($event)">
<div class="hidden-columns" ref="hiddenColumns"><slot></slot></div> <div class="hidden-columns" ref="hiddenColumns"><slot></slot></div>
<div class="el-table__header-wrapper" ref="headerWrapper" v-if="showHeader"> <div class="el-table__header-wrapper" ref="headerWrapper" v-if="showHeader">

View File

@ -325,15 +325,11 @@
} }
@e body { @e body {
td { tr.hover-row > td {
transition: background-color .25s ease;
}
tr.hover-row td {
background-color: #eff2f7; background-color: #eff2f7;
} }
tr.current-row td { tr.current-row > td {
background: #eff7ff; background: #eff7ff;
} }
} }
@ -364,5 +360,17 @@
color: #99a9bf; color: #99a9bf;
} }
} }
@modifier enable-row-transition {
.el-table__body td {
transition: background-color .25s ease;
}
}
@modifier enable-row-hover {
tr:hover > td {
background-color: #eff2f7;
}
}
} }
} }

View File

@ -1054,7 +1054,7 @@ describe('Table', () => {
const vm = createVue({ const vm = createVue({
template: ` template: `
<el-table :data="testData"> <el-table :data="testData">
<el-table-column prop="name" label="片名" /> <el-table-column prop="name" label="片名" fixed />
<el-table-column prop="release" label="发行日期" /> <el-table-column prop="release" label="发行日期" />
<el-table-column prop="director" label="导演" /> <el-table-column prop="director" label="导演" />
<el-table-column prop="runtime" label="时长(分)" /> <el-table-column prop="runtime" label="时长(分)" />