perf: table

pull/3784/head
tangjinzhou 2021-02-28 23:34:04 +08:00
parent 7f4eba3e93
commit e427ca15bf
15 changed files with 169 additions and 288 deletions

View File

@ -8,43 +8,19 @@ export default {
name: 'SelectionBox',
mixins: [BaseMixin],
props: SelectionBoxProps,
data() {
return {
checked: this.getCheckState(this.$props),
};
},
mounted() {
this.subscribe();
},
beforeDestroy() {
if (this.unsubscribe) {
this.unsubscribe();
}
},
methods: {
getCheckState(props) {
const { store, defaultSelection, rowIndex } = props;
computed: {
checked() {
const { store, defaultSelection, rowIndex } = this.$props;
let checked = false;
if (store.getState().selectionDirty) {
checked = store.getState().selectedRowKeys.indexOf(rowIndex) >= 0;
if (store.selectionDirty) {
checked = store.selectedRowKeys.indexOf(rowIndex) >= 0;
} else {
checked =
store.getState().selectedRowKeys.indexOf(rowIndex) >= 0 ||
defaultSelection.indexOf(rowIndex) >= 0;
store.selectedRowKeys.indexOf(rowIndex) >= 0 || defaultSelection.indexOf(rowIndex) >= 0;
}
return checked;
},
subscribe() {
const { store } = this;
this.unsubscribe = store.subscribe(() => {
const checked = this.getCheckState(this.$props);
this.setState({ checked });
});
},
},
render() {
const { type, rowIndex, ...rest } = getOptionProps(this);
const { checked } = this;

View File

@ -16,7 +16,7 @@ function checkSelection({
}) {
return byDefaultChecked
? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked)
: data[type]((item, i) => store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0);
: data[type]((item, i) => store.selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0);
}
function getIndeterminateState(props) {
@ -52,7 +52,7 @@ function getIndeterminateState(props) {
byDefaultChecked: true,
});
if (store.getState().selectionDirty) {
if (store.selectionDirty) {
return someCheckedNotByDefaultChecked;
}
return someCheckedNotByDefaultChecked || someCheckedByDefaultChecked;
@ -63,7 +63,7 @@ function getCheckState(props) {
if (!data.length) {
return false;
}
if (store.getState().selectionDirty) {
if (store.selectionDirty) {
return checkSelection({
...props,
data,
@ -105,7 +105,6 @@ export default {
text: props.locale.selectInvert,
},
];
return {
checked: getCheckState(props),
indeterminate: getIndeterminateState(props),
@ -118,18 +117,10 @@ export default {
this.setCheckState(this.$props);
},
deep: true,
immediate: true,
},
},
mounted() {
this.subscribe();
},
beforeDestroy() {
if (this.unsubscribe) {
this.unsubscribe();
}
},
methods: {
checkSelection(props, data, type, byDefaultChecked) {
const { store, getCheckboxPropsByItem, getRecordKey } = props || this.$props;
@ -137,9 +128,7 @@ export default {
if (type === 'every' || type === 'some') {
return byDefaultChecked
? data[type]((item, i) => getCheckboxPropsByItem(item, i).props.defaultChecked)
: data[type](
(item, i) => store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0,
);
: data[type]((item, i) => store.selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0);
}
return false;
},
@ -163,12 +152,6 @@ export default {
const { checked } = e.target;
this.$emit('select', checked ? 'all' : 'removeAll', 0, null);
},
subscribe() {
const { store } = this;
this.unsubscribe = store.subscribe(() => {
this.setCheckState(this.$props);
});
},
renderMenus(selections) {
return selections.map((selection, index) => {

View File

@ -2,7 +2,6 @@ import VcTable, { INTERNAL_COL_DEFINE } from '../vc-table';
import classNames from 'classnames';
import shallowEqual from 'shallowequal';
import FilterDropdown from './filterDropdown';
import createStore from './createStore';
import SelectionBox from './SelectionBox';
import SelectionCheckboxAll from './SelectionCheckboxAll';
import Column from './Column';
@ -21,6 +20,7 @@ import defaultLocale from '../locale-provider/default';
import warning from '../_util/warning';
import scrollTo from '../_util/scrollTo';
import TransButton from '../_util/transButton';
import Vue from 'vue';
function noop() {}
@ -112,6 +112,14 @@ export default {
Column,
ColumnGroup,
mixins: [BaseMixin],
inject: {
configProvider: { default: () => ConfigConsumerProps },
},
provide() {
return {
store: this.store,
};
},
props: initDefaultProps(TableProps, {
dataSource: [],
useFixedHeader: false,
@ -127,18 +135,7 @@ export default {
childrenColumnName: 'children',
}),
inject: {
configProvider: { default: () => ConfigConsumerProps },
},
// CheckboxPropsCache: {
// [key: string]: any;
// };
// store: Store;
// columns: ColumnProps<T>[];
// components: TableComponents;
data() {
// this.columns = props.columns || normalizeColumns(props.children)
const props = getOptionProps(this);
warning(
!props.expandedRowRender || !('scroll' in props) || !props.scroll.x,
@ -146,7 +143,7 @@ export default {
);
this.CheckboxPropsCache = {};
this.store = createStore({
this.store = Vue.observable({
selectedRowKeys: getRowSelection(this.$props).selectedRowKeys || [],
selectionDirty: false,
});
@ -179,26 +176,20 @@ export default {
rowSelection: {
handler(val, oldVal) {
if (val && 'selectedRowKeys' in val) {
this.store.setState({
selectedRowKeys: val.selectedRowKeys || [],
});
this.store.selectedRowKeys = val.selectedRowKeys || [];
const { rowSelection } = this;
if (rowSelection && val.getCheckboxProps !== rowSelection.getCheckboxProps) {
this.CheckboxPropsCache = {};
}
} else if (oldVal && !val) {
this.store.setState({
selectedRowKeys: [],
});
this.store.selectedRowKeys = [];
}
},
deep: true,
},
dataSource() {
this.store.setState({
selectionDirty: false,
});
this.store.selectionDirty = false;
this.CheckboxPropsCache = {};
},
@ -460,7 +451,7 @@ export default {
const { selectWay, record, checked, changeRowKeys, nativeEvent } = selectionInfo;
const rowSelection = getRowSelection(this.$props);
if (rowSelection && !('selectedRowKeys' in rowSelection)) {
this.store.setState({ selectedRowKeys });
this.store.selectedRowKeys = selectedRowKeys;
}
const data = this.getFlatData();
if (!rowSelection.onChange && !rowSelection[selectWay]) {
@ -573,9 +564,7 @@ export default {
this.setState(newState, () => {
this.scrollToFirstRow();
this.store.setState({
selectionDirty: false,
});
this.store.selectionDirty = false;
this.$emit(
'change',
...this.prepareParamsArguments({
@ -591,10 +580,8 @@ export default {
handleSelect(record, rowIndex, e) {
const checked = e.target.checked;
const nativeEvent = e.nativeEvent;
const defaultSelection = this.store.getState().selectionDirty
? []
: this.getDefaultSelection();
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const defaultSelection = this.store.selectionDirty ? [] : this.getDefaultSelection();
let selectedRowKeys = this.store.selectedRowKeys.concat(defaultSelection);
const key = this.getRecordKey(record, rowIndex);
const { pivot } = this.$data;
const rows = this.getFlatCurrentPageData();
@ -627,9 +614,7 @@ export default {
}
this.setState({ pivot: realIndex });
this.store.setState({
selectionDirty: true,
});
this.store.selectionDirty = true;
this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelectMultiple',
record,
@ -644,9 +629,7 @@ export default {
selectedRowKeys = selectedRowKeys.filter(i => key !== i);
}
this.setState({ pivot: realIndex });
this.store.setState({
selectionDirty: true,
});
this.store.selectionDirty = true;
this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelect',
record,
@ -662,9 +645,7 @@ export default {
const nativeEvent = e.nativeEvent;
const key = this.getRecordKey(record, rowIndex);
const selectedRowKeys = [key];
this.store.setState({
selectionDirty: true,
});
this.store.selectionDirty = true;
this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelect',
record,
@ -676,10 +657,8 @@ export default {
handleSelectRow(selectionKey, index, onSelectFunc) {
const data = this.getFlatCurrentPageData();
const defaultSelection = this.store.getState().selectionDirty
? []
: this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const defaultSelection = this.store.selectionDirty ? [] : this.getDefaultSelection();
const selectedRowKeys = this.store.selectedRowKeys.concat(defaultSelection);
const changeableRowKeys = data
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).props.disabled)
.map((item, i) => this.getRecordKey(item, i));
@ -724,9 +703,7 @@ export default {
break;
}
this.store.setState({
selectionDirty: true,
});
this.store.selectionDirty = true;
// when select custom selection, callback selections[n].onSelect
const { rowSelection } = this;
let customSelectionStartIndex = 2;
@ -769,9 +746,7 @@ export default {
}
this.setState(newState, this.scrollToFirstRow);
this.store.setState({
selectionDirty: false,
});
this.store.selectionDirty = false;
this.$emit(
'change',
...this.prepareParamsArguments({

View File

@ -1,10 +1,9 @@
import Vue from 'vue';
import { mount } from '@vue/test-utils';
import createStore from '../createStore';
import SelectionBox from '../SelectionBox';
const getDefaultStore = selectedRowKeys => {
return createStore({
return Vue.observable({
selectedRowKeys: selectedRowKeys || [],
selectionDirty: false,
});
@ -26,7 +25,7 @@ describe('SelectionBox', () => {
sync: false,
});
expect(wrapper.vm.$data).toEqual({ checked: false });
expect(wrapper.vm.checked).toEqual(false);
});
it('checked by selectedRowKeys ', () => {
@ -44,7 +43,7 @@ describe('SelectionBox', () => {
sync: false,
});
expect(wrapper.vm.$data).toEqual({ checked: true });
expect(wrapper.vm.checked).toEqual(true);
});
it('checked by defaultSelection', () => {
@ -62,7 +61,7 @@ describe('SelectionBox', () => {
sync: false,
});
expect(wrapper.vm.$data).toEqual({ checked: true });
expect(wrapper.vm.checked).toEqual(true);
});
it('checked when store change', () => {
@ -80,12 +79,10 @@ describe('SelectionBox', () => {
sync: false,
});
store.setState({
selectedRowKeys: ['1'],
selectionDirty: true,
});
store.selectedRowKeys = ['1'];
store.selectionDirty = true;
expect(wrapper.vm.$data).toEqual({ checked: true });
expect(wrapper.vm.checked).toEqual(true);
});
it('passes props to Checkbox', done => {

View File

@ -48,7 +48,7 @@ describe('Table.rowSelection', () => {
checkboxAll.element.checked = true;
checkboxAll.trigger('change');
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0, 1, 2, 3],
selectionDirty: true,
});
@ -56,7 +56,7 @@ describe('Table.rowSelection', () => {
checkboxes.at(1).element.checked = false;
checkboxes.at(1).trigger('change');
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1, 2, 3],
selectionDirty: true,
});
@ -64,7 +64,7 @@ describe('Table.rowSelection', () => {
checkboxes.at(1).element.checked = true;
checkboxes.at(1).trigger('change');
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1, 2, 3, 0],
selectionDirty: true,
});
@ -79,7 +79,7 @@ describe('Table.rowSelection', () => {
radios.at(0).element.checked = true;
radios.at(0).trigger('change');
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0],
selectionDirty: true,
});
@ -87,7 +87,7 @@ describe('Table.rowSelection', () => {
radios.at(radios.length - 1).element.checked = true;
radios.at(radios.length - 1).trigger('change');
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [3],
selectionDirty: true,
});
@ -164,14 +164,14 @@ describe('Table.rowSelection', () => {
it('can be controlled', async () => {
const wrapper = mount(Table, getTableOptions({ rowSelection: { selectedRowKeys: [0] } }));
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0],
selectionDirty: false,
});
wrapper.setProps({ rowSelection: { selectedRowKeys: [1] } });
await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({
expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1],
selectionDirty: false,
});
@ -705,7 +705,9 @@ describe('Table.rowSelection', () => {
checkboxes.at(1).element.checked = true;
checkboxes.at(1).trigger('change');
expect(checkboxAll.vm.$data).toEqual({ indeterminate: true, checked: false });
await asyncExpect(() => {
expect(checkboxAll.vm.$data).toEqual({ indeterminate: true, checked: false });
});
checkboxes.at(2).element.checked = true;
checkboxes.at(2).trigger('change');

View File

@ -1,10 +1,8 @@
import PropTypes from '../_util/vue-types';
import { Store } from './createStore';
import { getListeners } from '../_util/props-util';
const BodyRowProps = {
store: Store,
store: PropTypes.any,
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
prefixCls: PropTypes.string,
};
@ -13,36 +11,11 @@ export default function createBodyRow(Component = 'tr') {
const BodyRow = {
name: 'BodyRow',
props: BodyRowProps,
data() {
const { selectedRowKeys } = this.store.getState();
return {
selected: selectedRowKeys.indexOf(this.rowKey) >= 0,
};
},
mounted() {
this.subscribe();
},
beforeDestroy() {
if (this.unsubscribe) {
this.unsubscribe();
}
},
methods: {
subscribe() {
const { store, rowKey } = this;
this.unsubscribe = store.subscribe(() => {
const { selectedRowKeys } = this.store.getState();
const selected = selectedRowKeys.indexOf(rowKey) >= 0;
if (selected !== this.selected) {
this.selected = selected;
}
});
computed: {
selected() {
return this.$props.store.selectedRowKeys.indexOf(this.$props.rowKey) >= 0;
},
},
render() {
const className = {
[`${this.prefixCls}-row-selected`]: this.selected,

View File

@ -1,11 +0,0 @@
import PropTypes from '../_util/vue-types';
export const Store = PropTypes.shape({
setState: PropTypes.func,
getState: PropTypes.func,
subscribe: PropTypes.func,
}).loose;
import create from '../_util/store/create';
const createStore = create;
export default createStore;

View File

@ -1,7 +1,6 @@
import PropTypes from '../_util/vue-types';
import { PaginationProps as getPaginationProps } from '../pagination';
import { SpinProps as getSpinProps } from '../spin';
import { Store } from './createStore';
const PaginationProps = getPaginationProps();
const SpinProps = getSpinProps();
@ -162,7 +161,7 @@ export const TableProps = {
// }
export const SelectionCheckboxAllProps = {
store: Store,
store: PropTypes.any,
locale: PropTypes.any,
disabled: PropTypes.bool,
getCheckboxPropsByItem: PropTypes.func,
@ -181,7 +180,7 @@ export const SelectionCheckboxAllProps = {
// }
export const SelectionBoxProps = {
store: Store,
store: PropTypes.any,
type: RowSelectionType,
defaultSelection: PropTypes.arrayOf([PropTypes.string, PropTypes.number]),
rowIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

View File

@ -5,7 +5,6 @@ import TableHeader from './TableHeader';
import TableRow from './TableRow';
import ExpandableRow from './ExpandableRow';
import { mergeProps, getListeners } from '../../_util/props-util';
import { connect } from '../../_util/store';
function noop() {}
const BaseTable = {
name: 'BaseTable',
@ -15,13 +14,13 @@ const BaseTable = {
tableClassName: PropTypes.string.isRequired,
hasHead: PropTypes.bool.isRequired,
hasBody: PropTypes.bool.isRequired,
store: PropTypes.object.isRequired,
expander: PropTypes.object.isRequired,
getRowKey: PropTypes.func,
isAnyColumnsFixed: PropTypes.bool,
},
inject: {
table: { default: () => ({}) },
store: { from: 'table-store', default: () => ({}) },
},
methods: {
getColumns(cols) {
@ -37,9 +36,7 @@ const BaseTable = {
}));
},
handleRowHover(isHover, key) {
this.store.setState({
currentHoverKey: isHover ? key : null,
});
this.store.currentHoverKey = isHover ? key : null;
},
renderRows(renderData, indent, ancestorKeys = []) {
@ -187,4 +184,4 @@ const BaseTable = {
},
};
export default connect()(BaseTable);
export default BaseTable;

View File

@ -1,7 +1,6 @@
import PropTypes from '../../_util/vue-types';
import ExpandIcon from './ExpandIcon';
import BaseMixin from '../../_util/BaseMixin';
import { connect } from '../../_util/store';
const ExpandableRow = {
mixins: [BaseMixin],
@ -14,7 +13,6 @@ const ExpandableRow = {
indentSize: PropTypes.number,
needIndentSpaced: PropTypes.bool.isRequired,
expandRowByClick: PropTypes.bool,
expanded: PropTypes.bool.isRequired,
expandIconAsCell: PropTypes.bool,
expandIconColumnIndex: PropTypes.number,
childrenColumnName: PropTypes.string,
@ -24,7 +22,14 @@ const ExpandableRow = {
// onRowClick: PropTypes.func,
// children: PropTypes.func.isRequired,
},
inject: {
store: { from: 'table-store', default: () => ({}) },
},
computed: {
expanded() {
return this.store.expandedRowKeys.includes(this.$props.rowKey);
},
},
beforeDestroy() {
this.handleDestroy();
},
@ -128,6 +133,4 @@ const ExpandableRow = {
},
};
export default connect(({ expandedRowKeys }, { rowKey }) => ({
expanded: expandedRowKeys.includes(rowKey),
}))(ExpandableRow);
export default ExpandableRow;

View File

@ -1,6 +1,5 @@
import PropTypes from '../../_util/vue-types';
import BaseMixin from '../../_util/BaseMixin';
import { connect } from '../../_util/store';
import shallowEqual from 'shallowequal';
import TableRow from './TableRow';
import { remove } from './utils';
@ -21,7 +20,6 @@ export const ExpandableTableProps = () => ({
// onExpand: PropTypes.func,
// onExpandedRowsChange: PropTypes.func,
columnManager: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
prefixCls: PropTypes.string.isRequired,
data: PropTypes.array,
getRowKey: PropTypes.func,
@ -39,7 +37,9 @@ const ExpandableTable = {
childrenColumnName: 'children',
indentSize: 15,
}),
inject: {
store: { from: 'table-store', default: () => ({}) },
},
data() {
const {
data,
@ -66,10 +66,8 @@ const ExpandableTable = {
// this.columnManager = props.columnManager
// this.store = props.store
this.store.setState({
expandedRowsHeight: {},
expandedRowKeys: finalExpandedRowKeys,
});
this.store.expandedRowsHeight = {};
this.store.expandedRowKeys = finalExpandedRowKeys;
return {};
},
mounted() {
@ -81,9 +79,7 @@ const ExpandableTable = {
watch: {
expandedRowKeys(val) {
this.$nextTick(() => {
this.store.setState({
expandedRowKeys: val,
});
this.store.expandedRowKeys = val;
});
},
},
@ -98,7 +94,7 @@ const ExpandableTable = {
event.stopPropagation();
}
let { expandedRowKeys } = this.store.getState();
let { expandedRowKeys } = this.store;
if (expanded) {
// row was expaned
@ -112,7 +108,7 @@ const ExpandableTable = {
}
if (!this.expandedRowKeys) {
this.store.setState({ expandedRowKeys });
this.store.expandedRowKeys = expandedRowKeys;
}
// De-dup of repeat call
if (!this.latestExpandedRows || !shallowEqual(this.latestExpandedRows, expandedRowKeys)) {
@ -163,7 +159,7 @@ const ExpandableTable = {
{
key: 'extra-row',
customRender: () => {
const { expandedRowKeys } = this.store.getState();
const { expandedRowKeys } = this.store;
const expanded = expandedRowKeys.includes(parentKey);
return {
attrs: {
@ -245,4 +241,4 @@ const ExpandableTable = {
},
};
export default connect()(ExpandableTable);
export default ExpandableTable;

View File

@ -7,17 +7,20 @@ import PropTypes from '../../_util/vue-types';
import { debounce } from './utils';
import warning from '../../_util/warning';
import addEventListener from '../../vc-util/Dom/addEventListener';
import { Provider, create } from '../../_util/store';
import ColumnManager from './ColumnManager';
import HeadTable from './HeadTable';
import BodyTable from './BodyTable';
import ExpandableTable from './ExpandableTable';
import { initDefaultProps, getOptionProps, getListeners } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import Vue from 'vue';
export default {
name: 'Table',
mixins: [BaseMixin],
provide() {
return { 'table-store': this.store, table: this };
},
props: initDefaultProps(
{
data: PropTypes.array,
@ -85,6 +88,13 @@ export default {
),
data() {
this.preData = [...this.data];
this.store = Vue.observable({
currentHoverKey: null,
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: {},
expandedRowsHeight: {},
expandedRowKeys: [],
});
return {
columnManager: new ColumnManager(this.columns),
sComponents: merge(
@ -158,23 +168,10 @@ export default {
'getBodyWrapper is deprecated, please use custom components instead.',
);
// this.columnManager = new ColumnManager(this.columns, this.$slots.default)
this.store = create({
currentHoverKey: null,
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: {},
});
this.setScrollPosition('left');
this.debouncedWindowResize = debounce(this.handleWindowResize, 150);
},
provide() {
return {
table: this,
};
},
mounted() {
this.$nextTick(() => {
@ -298,7 +295,7 @@ export default {
const fixedColumnsHeadRowsHeight = [].map.call(headRows, row =>
row.getBoundingClientRect().height ? row.getBoundingClientRect().height - 0.5 : 'auto',
);
const state = this.store.getState();
const state = this.store;
const fixedColumnsBodyRowsHeight = [].reduce.call(
bodyRows,
(acc, row) => {
@ -318,10 +315,8 @@ export default {
) {
return;
}
this.store.setState({
fixedColumnsHeadRowsHeight,
fixedColumnsBodyRowsHeight,
});
this.store.fixedColumnsHeadRowsHeight = fixedColumnsHeadRowsHeight;
this.store.fixedColumnsBodyRowsHeight = fixedColumnsBodyRowsHeight;
},
resetScrollX() {
@ -591,10 +586,6 @@ export default {
},
},
};
return (
<Provider store={this.store}>
<ExpandableTable {...expandableTableProps} />
</Provider>
);
return <ExpandableTable {...expandableTableProps} />;
},
};

View File

@ -1,9 +1,11 @@
import classNames from 'classnames';
import PropTypes from '../../_util/vue-types';
import { connect } from '../../_util/store';
import { mergeProps } from '../../_util/props-util';
const TableHeaderRow = {
inject: {
store: { from: 'table-store', default: () => ({}) },
},
props: {
index: PropTypes.number,
fixed: PropTypes.string,
@ -11,11 +13,29 @@ const TableHeaderRow = {
rows: PropTypes.array,
row: PropTypes.array,
components: PropTypes.object,
height: PropTypes.any,
customHeaderRow: PropTypes.func,
prefixCls: PropTypes.prefixCls,
prefixCls: PropTypes.string,
},
name: 'TableHeaderRow',
computed: {
height() {
const { fixedColumnsHeadRowsHeight } = this.store;
const { columns, rows, fixed } = this.$props;
const headerHeight = fixedColumnsHeadRowsHeight[0];
if (!fixed) {
return null;
}
if (headerHeight && columns) {
if (headerHeight === 'auto') {
return 'auto';
}
return `${headerHeight / rows.length}px`;
}
return null;
},
},
render(h) {
const { row, index, height, components, customHeaderRow, prefixCls } = this;
const HeaderRow = components.header.row;
@ -73,26 +93,4 @@ const TableHeaderRow = {
},
};
function getRowHeight(state, props) {
const { fixedColumnsHeadRowsHeight } = state;
const { columns, rows, fixed } = props;
const headerHeight = fixedColumnsHeadRowsHeight[0];
if (!fixed) {
return null;
}
if (headerHeight && columns) {
if (headerHeight === 'auto') {
return 'auto';
}
return `${headerHeight / rows.length}px`;
}
return null;
}
export default connect((state, props) => {
return {
height: getRowHeight(state, props),
};
})(TableHeaderRow);
export default TableHeaderRow;

View File

@ -1,6 +1,5 @@
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';
@ -9,6 +8,9 @@ function noop() {}
const TableRow = {
name: 'TableRow',
mixins: [BaseMixin],
inject: {
store: { from: 'table-store', default: () => ({}) },
},
props: initDefaultProps(
{
customRow: PropTypes.func,
@ -21,16 +23,12 @@ const TableRow = {
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,
@ -53,6 +51,37 @@ const TableRow = {
},
),
computed: {
visible() {
const { expandedRowKeys } = this.store;
const { ancestorKeys } = this.$props;
return !!(ancestorKeys.length === 0 || ancestorKeys.every(k => expandedRowKeys.includes(k)));
},
height() {
const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = this.store;
const { fixed, rowKey } = this.$props;
if (!fixed) {
return null;
}
if (expandedRowsHeight[rowKey]) {
return expandedRowsHeight[rowKey];
}
if (fixedColumnsBodyRowsHeight[rowKey]) {
return fixedColumnsBodyRowsHeight[rowKey];
}
return null;
},
hovered() {
const { currentHoverKey } = this.store;
const { rowKey } = this.$props;
return currentHoverKey === rowKey;
},
},
data() {
// this.shouldRender = this.visible
return {
@ -68,10 +97,13 @@ const TableRow = {
}
},
watch: {
visible(val) {
if (val) {
this.shouldRender = true;
}
visible: {
handler(val) {
if (val) {
this.shouldRender = true;
}
},
immediate: true,
},
},
@ -117,25 +149,23 @@ const TableRow = {
setExpandedRowHeight() {
const { store, rowKey } = this;
let { expandedRowsHeight } = store.getState();
let { expandedRowsHeight } = store;
const height = this.rowRef.getBoundingClientRect().height;
expandedRowsHeight = {
...expandedRowsHeight,
[rowKey]: height,
};
store.setState({ expandedRowsHeight });
store.expandedRowsHeight = expandedRowsHeight;
},
setRowHeight() {
const { store, rowKey } = this;
const { fixedColumnsBodyRowsHeight } = store.getState();
const { fixedColumnsBodyRowsHeight } = store;
const height = this.rowRef.getBoundingClientRect().height;
store.setState({
fixedColumnsBodyRowsHeight: {
...fixedColumnsBodyRowsHeight,
[rowKey]: height,
},
});
store.fixedColumnsBodyRowsHeight = {
...fixedColumnsBodyRowsHeight,
[rowKey]: height,
};
},
getStyle() {
@ -279,33 +309,4 @@ const TableRow = {
},
};
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);
export default TableRow;

1
v2-doc Submodule

@ -0,0 +1 @@
Subproject commit 0468ad3010f71ad6b267c66c4f5e28c89c19d83e