mirror of https://github.com/ElemeFE/element
Table: improve performance in large data. (#1298)
parent
e3ac607938
commit
631037c296
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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="时长(分)" />
|
||||||
|
|
Loading…
Reference in New Issue