ant-design-vue/components/vc-table/src/TableRow.jsx

312 lines
7.8 KiB
Vue

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(
<TableCell
prefixCls={prefixCls}
record={record}
indentSize={indentSize}
indent={indent}
index={index}
column={column}
key={column.key || column.dataIndex}
expandIcon={hasExpandIcon(i) && renderExpandIcon()}
component={BodyCell}
/>,
);
}
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 <BodyRow {...bodyRowProps}>{cells}</BodyRow>;
},
};
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);