import classNames from 'classnames'; import PropTypes from '../../_util/vue-types'; import { connect } from '../../_util/store'; import TableCell from './TableCell'; import { initDefaultProps, mergeProps, getStyle } from '../../_util/props-util'; import BaseMixin from '../../_util/BaseMixin'; import warning from '../../_util/warning'; function noop() {} const TableRow = { name: 'TableRow', mixins: [BaseMixin], props: initDefaultProps( { customRow: PropTypes.func, // onRowClick: PropTypes.func, // onRowDoubleClick: PropTypes.func, // onRowContextMenu: PropTypes.func, // onRowMouseEnter: PropTypes.func, // onRowMouseLeave: PropTypes.func, record: PropTypes.object, prefixCls: PropTypes.string, // onHover: PropTypes.func, columns: PropTypes.array, height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), index: PropTypes.number, rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, className: PropTypes.string, indent: PropTypes.number, indentSize: PropTypes.number, hasExpandIcon: PropTypes.func, hovered: PropTypes.bool.isRequired, visible: PropTypes.bool.isRequired, store: PropTypes.object.isRequired, fixed: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), renderExpandIcon: PropTypes.func, renderExpandIconCell: PropTypes.func, components: PropTypes.any, expandedRow: PropTypes.bool, isAnyColumnsFixed: PropTypes.bool, ancestorKeys: PropTypes.array.isRequired, expandIconColumnIndex: PropTypes.number, expandRowByClick: PropTypes.bool, // visible: PropTypes.bool, // hovered: PropTypes.bool, // height: PropTypes.any, }, { // expandIconColumnIndex: 0, // expandRowByClick: false, hasExpandIcon() {}, renderExpandIcon() {}, renderExpandIconCell() {}, }, ), data() { // this.shouldRender = this.visible return { shouldRender: this.visible, }; }, mounted() { if (this.shouldRender) { this.$nextTick(() => { this.saveRowRef(); }); } }, watch: { visible(val) { if (val) { this.shouldRender = true; } }, }, updated() { if (this.shouldRender && !this.rowRef) { this.$nextTick(() => { this.saveRowRef(); }); } }, methods: { onRowClick(event, rowPropFunc = noop) { const { record, index } = this; this.__emit('rowClick', record, index, event); rowPropFunc(event); }, onRowDoubleClick(event, rowPropFunc = noop) { const { record, index } = this; this.__emit('rowDoubleClick', record, index, event); rowPropFunc(event); }, onContextMenu(event, rowPropFunc = noop) { const { record, index } = this; this.__emit('rowContextmenu', record, index, event); rowPropFunc(event); }, onMouseEnter(event, rowPropFunc = noop) { const { record, index, rowKey } = this; this.__emit('hover', true, rowKey); this.__emit('rowMouseenter', record, index, event); rowPropFunc(event); }, onMouseLeave(event, rowPropFunc = noop) { const { record, index, rowKey } = this; this.__emit('hover', false, rowKey); this.__emit('rowMouseleave', record, index, event); rowPropFunc(event); }, setExpandedRowHeight() { const { store, rowKey } = this; let { expandedRowsHeight } = store.getState(); const height = this.rowRef.getBoundingClientRect().height; expandedRowsHeight = { ...expandedRowsHeight, [rowKey]: height, }; store.setState({ expandedRowsHeight }); }, setRowHeight() { const { store, rowKey } = this; const { fixedColumnsBodyRowsHeight } = store.getState(); const height = this.rowRef.getBoundingClientRect().height; store.setState({ fixedColumnsBodyRowsHeight: { ...fixedColumnsBodyRowsHeight, [rowKey]: height, }, }); }, getStyle() { const { height, visible } = this; let style = getStyle(this); if (height) { style = { ...style, height }; } if (!visible && !style.display) { style = { ...style, display: 'none' }; } return style; }, saveRowRef() { this.rowRef = this.$el; const { isAnyColumnsFixed, fixed, expandedRow, ancestorKeys } = this; if (!isAnyColumnsFixed) { return; } if (!fixed && expandedRow) { this.setExpandedRowHeight(); } if (!fixed && ancestorKeys.length >= 0) { this.setRowHeight(); } }, }, render() { if (!this.shouldRender) { return null; } const { prefixCls, columns, record, rowKey, index, customRow = noop, indent, indentSize, hovered, height, visible, components, hasExpandIcon, renderExpandIcon, renderExpandIconCell, } = this; const BodyRow = components.body.row; const BodyCell = components.body.cell; let className = ''; if (hovered) { className += ` ${prefixCls}-hover`; } const cells = []; renderExpandIconCell(cells); for (let i = 0; i < columns.length; i += 1) { const column = columns[i]; warning( column.onCellClick === undefined, 'column[onCellClick] is deprecated, please use column[customCell] instead.', ); cells.push( , ); } const { class: customClass, className: customClassName, style: customStyle, ...rowProps } = customRow(record, index) || {}; let style = { height: typeof height === 'number' ? `${height}px` : height }; if (!visible) { style.display = 'none'; } style = { ...style, ...customStyle }; const rowClassName = classNames( prefixCls, className, `${prefixCls}-level-${indent}`, customClassName, customClass, ); const rowPropEvents = rowProps.on || {}; const bodyRowProps = mergeProps( { ...rowProps, style }, { on: { click: e => { this.onRowClick(e, rowPropEvents.click); }, dblclick: e => { this.onRowDoubleClick(e, rowPropEvents.dblclick); }, mouseenter: e => { this.onMouseEnter(e, rowPropEvents.mouseenter); }, mouseleave: e => { this.onMouseLeave(e, rowPropEvents.mouseleave); }, contextmenu: e => { this.onContextMenu(e, rowPropEvents.contextmenu); }, }, class: rowClassName, }, { attrs: { 'data-row-key': rowKey, }, }, ); return {cells}; }, }; function getRowHeight(state, props) { const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = state; const { fixed, rowKey } = props; if (!fixed) { return null; } if (expandedRowsHeight[rowKey]) { return expandedRowsHeight[rowKey]; } if (fixedColumnsBodyRowsHeight[rowKey]) { return fixedColumnsBodyRowsHeight[rowKey]; } return null; } export default connect((state, props) => { const { currentHoverKey, expandedRowKeys } = state; const { rowKey, ancestorKeys } = props; const visible = ancestorKeys.length === 0 || ancestorKeys.every(k => expandedRowKeys.includes(k)); return { visible, hovered: currentHoverKey === rowKey, height: getRowHeight(state, props), }; })(TableRow);