说明
table-body
是表格的主体部分,也是较为简单,因此不细说。
源码解读
import { getCell, getColumnByCell, getRowIdentity } from './util';
import ElCheckbox from 'element-ui/packages/checkbox';
export default {
components: {
ElCheckbox
},
props: {
store: {
required: true
},
context: {},
layout: {
required: true
},
rowClassName: [String, Function],
rowStyle: [Object, Function],
fixed: String,
highlight: Boolean
},
render(h) {
// 计算要隐藏的列
const columnsHidden = this.columns.map((column, index) => this.isColumnHidden(index));
return (
{
this._l(this.columns, column =>
)
}
{
this._l(this.data, (row, $index) =>
[ 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={ [this.getRowClass(row, $index)] }>
{
this._l(this.columns, (column, cellIndex) =>
this.handleCellMouseEnter($event, row) }
on-mouseleave={ this.handleCellMouseLeave }>
{
columnsHidden[cellIndex] ? '' : column.renderCell.call(this._renderProxy, h, { row, column, $index, store: this.store, _self: this.context || this.table.$vnode.context })
}
)
}
{
!this.fixed && this.layout.scrollY && this.layout.gutterWidth ? : ''
}
,
this.store.states.expandRows.indexOf(row) > -1
? (
{ this.table.renderExpanded ? this.table.renderExpanded(h, { row, $index, store: this.store }) : ''}
)
: ''
]
)
}
);
},
watch: {
// 处理悬浮在某行,更改对应的样式
'store.states.hoverRow'(newVal, oldVal) {
if (!this.store.states.isComplex) return;
const el = this.$el;
if (!el) return;
const rows = el.querySelectorAll('tbody > tr');
const oldRow = rows[oldVal];
const newRow = rows[newVal];
if (oldRow) {
oldRow.classList.remove('hover-row');
}
if (newRow) {
newRow.classList.add('hover-row');
}
},
// 处理当前行改变
'store.states.currentRow'(newVal, oldVal) {
if (!this.highlight) return;
const el = this.$el;
if (!el) return;
const data = this.store.states.data;
const rows = el.querySelectorAll('tbody > tr');
const oldRow = rows[data.indexOf(oldVal)];
const newRow = rows[data.indexOf(newVal)];
if (oldRow) {
oldRow.classList.remove('current-row');
} else if (rows) {
[].forEach.call(rows, row => row.classList.remove('current-row'));
}
if (newRow) {
newRow.classList.add('current-row');
}
}
},
computed: {
table() {
return this.$parent;
},
data() {
return this.store.states.data;
},
columnsCount() {
return this.store.states.columns.length;
},
leftFixedCount() {
return this.store.states.fixedColumns.length;
},
rightFixedCount() {
return this.store.states.rightFixedColumns.length;
},
columns() {
return this.store.states.columns;
}
},
data() {
return {
tooltipDisabled: true
};
},
methods: {
// 获取行的 key,如果没有直接返回索引
getKeyOfRow(row, index) {
const rowKey = this.table.rowKey;
if (rowKey) {
return getRowIdentity(row, rowKey);
}
return index;
},
// 判断列是否隐藏
isColumnHidden(index) {
if (this.fixed === true || this.fixed === 'left') {
return index >= this.leftFixedCount;
} else if (this.fixed === 'right') {
return index < this.columnsCount - this.rightFixedCount;
} else {
return (index < this.leftFixedCount) || (index >= this.columnsCount - this.rightFixedCount);
}
},
// 获取对应行的样式
getRowStyle(row, index) {
const rowStyle = this.rowStyle;
if (typeof rowStyle === 'function') {
return rowStyle.call(null, row, index);
}
return rowStyle;
},
// 获取对应行的类
getRowClass(row, index) {
const classes = [];
const rowClassName = this.rowClassName;
if (typeof rowClassName === 'string') {
classes.push(rowClassName);
} else if (typeof rowClassName === 'function') {
classes.push(rowClassName.call(null, row, index) || '');
}
return classes.join(' ');
},
// 处理鼠标进入单元格
handleCellMouseEnter(event, row) {
const table = this.table;
// 获取进入的单元格
const cell = getCell(event);
if (cell) {
// 获取对应的列
const column = getColumnByCell(table, cell);
// 修改悬浮的状态
const hoverState = table.hoverState = {cell, column, row};
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
}
// 判断是否text-overflow, 如果是就显示tooltip
const cellChild = event.target.querySelector('.cell');
this.tooltipDisabled = cellChild.scrollWidth <= cellChild.offsetWidth;
},
// 处理鼠标离开单元格
handleCellMouseLeave(event) {
const cell = getCell(event);
if (!cell) return;
const oldHoverState = this.table.hoverState;
this.table.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
},
// 处理鼠标进入某行
handleMouseEnter(index) {
// 设置该行是鼠标悬浮的行
this.store.commit('setHoverRow', index);
},
// 处理鼠标离开某行
handleMouseLeave() {
this.store.commit('setHoverRow', null);
},
// 处理鼠标右键
handleContextMenu(event, row) {
const table = this.table;
table.$emit('row-contextmenu', row, event);
},
// 处理左键双击
handleDoubleClick(event, row) {
const table = this.table;
table.$emit('row-dblclick', row, event);
},
// 处理左键单击
handleClick(event, row) {
const table = this.table;
const cell = getCell(event);
let column;
if (cell) {
column = getColumnByCell(table, cell);
if (column) {
// 如果存在对应的单元格,并能找到对应的列,则触发 cell-click
table.$emit('cell-click', row, column, cell, event);
}
}
// 设置当前行
this.store.commit('setCurrentRow', row);
// 触发 row-click
table.$emit('row-click', row, event, column);
},
// 切换扩展项
handleExpandClick(row) {
this.store.commit('toggleRowExpanded', row);
}
}
};