From e427ca15bfef423c5272cf0057f08f6c006db7b5 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Sun, 28 Feb 2021 23:34:04 +0800 Subject: [PATCH] perf: table --- components/table/SelectionBox.jsx | 36 ++----- components/table/SelectionCheckboxAll.jsx | 27 +----- components/table/Table.jsx | 73 +++++--------- .../table/__tests__/SelectionBox.test.js | 17 ++-- .../__tests__/Table.rowSelection.test.js | 18 ++-- components/table/createBodyRow.jsx | 35 +------ components/table/createStore.jsx | 11 --- components/table/interface.js | 5 +- components/vc-table/src/BaseTable.jsx | 9 +- components/vc-table/src/ExpandableRow.jsx | 15 +-- components/vc-table/src/ExpandableTable.jsx | 24 ++--- components/vc-table/src/Table.jsx | 39 +++----- components/vc-table/src/TableHeaderRow.jsx | 50 +++++----- components/vc-table/src/TableRow.jsx | 97 ++++++++++--------- v2-doc | 1 + 15 files changed, 169 insertions(+), 288 deletions(-) delete mode 100644 components/table/createStore.jsx create mode 160000 v2-doc diff --git a/components/table/SelectionBox.jsx b/components/table/SelectionBox.jsx index bbce3b519..d16626bb3 100644 --- a/components/table/SelectionBox.jsx +++ b/components/table/SelectionBox.jsx @@ -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; diff --git a/components/table/SelectionCheckboxAll.jsx b/components/table/SelectionCheckboxAll.jsx index dbe4db0f0..afa112eb1 100644 --- a/components/table/SelectionCheckboxAll.jsx +++ b/components/table/SelectionCheckboxAll.jsx @@ -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) => { diff --git a/components/table/Table.jsx b/components/table/Table.jsx index 73e7a9933..ff5a2032b 100755 --- a/components/table/Table.jsx +++ b/components/table/Table.jsx @@ -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[]; - // 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({ diff --git a/components/table/__tests__/SelectionBox.test.js b/components/table/__tests__/SelectionBox.test.js index e3157c41a..c3933163d 100644 --- a/components/table/__tests__/SelectionBox.test.js +++ b/components/table/__tests__/SelectionBox.test.js @@ -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 => { diff --git a/components/table/__tests__/Table.rowSelection.test.js b/components/table/__tests__/Table.rowSelection.test.js index 076593aed..911e2b390 100644 --- a/components/table/__tests__/Table.rowSelection.test.js +++ b/components/table/__tests__/Table.rowSelection.test.js @@ -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'); diff --git a/components/table/createBodyRow.jsx b/components/table/createBodyRow.jsx index a31f53427..d1df92824 100644 --- a/components/table/createBodyRow.jsx +++ b/components/table/createBodyRow.jsx @@ -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, diff --git a/components/table/createStore.jsx b/components/table/createStore.jsx deleted file mode 100644 index e8e171ee3..000000000 --- a/components/table/createStore.jsx +++ /dev/null @@ -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; diff --git a/components/table/interface.js b/components/table/interface.js index eee9338f8..45b41dd19 100644 --- a/components/table/interface.js +++ b/components/table/interface.js @@ -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]), diff --git a/components/vc-table/src/BaseTable.jsx b/components/vc-table/src/BaseTable.jsx index 640a34331..87ba9033e 100644 --- a/components/vc-table/src/BaseTable.jsx +++ b/components/vc-table/src/BaseTable.jsx @@ -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; diff --git a/components/vc-table/src/ExpandableRow.jsx b/components/vc-table/src/ExpandableRow.jsx index 09d5db4d9..eea3960c2 100644 --- a/components/vc-table/src/ExpandableRow.jsx +++ b/components/vc-table/src/ExpandableRow.jsx @@ -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; diff --git a/components/vc-table/src/ExpandableTable.jsx b/components/vc-table/src/ExpandableTable.jsx index 6f75a1726..1cf4d1366 100644 --- a/components/vc-table/src/ExpandableTable.jsx +++ b/components/vc-table/src/ExpandableTable.jsx @@ -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; diff --git a/components/vc-table/src/Table.jsx b/components/vc-table/src/Table.jsx index 90dce9b5c..0e4c08ead 100644 --- a/components/vc-table/src/Table.jsx +++ b/components/vc-table/src/Table.jsx @@ -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 ( - - - - ); + return ; }, }; diff --git a/components/vc-table/src/TableHeaderRow.jsx b/components/vc-table/src/TableHeaderRow.jsx index 38c93f839..8ee58f803 100644 --- a/components/vc-table/src/TableHeaderRow.jsx +++ b/components/vc-table/src/TableHeaderRow.jsx @@ -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; diff --git a/components/vc-table/src/TableRow.jsx b/components/vc-table/src/TableRow.jsx index e15112a1f..3109b68da 100644 --- a/components/vc-table/src/TableRow.jsx +++ b/components/vc-table/src/TableRow.jsx @@ -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; diff --git a/v2-doc b/v2-doc new file mode 160000 index 000000000..0468ad301 --- /dev/null +++ b/v2-doc @@ -0,0 +1 @@ +Subproject commit 0468ad3010f71ad6b267c66c4f5e28c89c19d83e