This commit is contained in:
tangjinzhou 2021-02-27 22:50:21 +08:00
parent f589c8f723
commit e6b7aa47ae
23 changed files with 224 additions and 550 deletions

View File

@ -28,4 +28,5 @@ components/style/color/*.less
.huskyrc .huskyrc
.gitmodules .gitmodules
*.png *.png
v2-doc/

View File

@ -1,7 +0,0 @@
import PropTypes from '../vue-types';
export const storeShape = PropTypes.shape({
subscribe: PropTypes.func.isRequired,
setState: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired,
});

View File

@ -1,15 +0,0 @@
import { provide } from 'vue';
import { storeShape } from './PropTypes';
import { getSlot } from '../props-util';
export default {
name: 'StoreProvider',
props: {
store: storeShape.isRequired,
},
created() {
provide('storeContext', this.$props);
},
render() {
return getSlot(this);
},
};

View File

@ -1,108 +0,0 @@
import shallowEqual from '../shallowequal';
import { inject, createVNode, watchEffect, defineComponent, provide } from 'vue';
import omit from 'omit.js';
import { getOptionProps } from '../props-util';
function getDisplayName(WrappedComponent) {
return WrappedComponent.name || 'Component';
}
const defaultMapStateToProps = () => ({});
export default function connect(mapStateToProps, injectExtraPropsKey) {
const shouldSubscribe = !!mapStateToProps;
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps;
return function wrapWithConnect(WrappedComponent) {
const tempProps = omit(WrappedComponent.props || {}, ['store']);
const props = {};
Object.keys(tempProps).forEach(k => {
props[k] = { ...tempProps[k], required: false };
});
const Connect = {
name: `Connect_${getDisplayName(WrappedComponent)}`,
inheritAttrs: false,
props,
setup() {
provide(injectExtraPropsKey, undefined); // injectExtraPropsKey
return {
storeContext: inject('storeContext', {}),
injectExtraProps: injectExtraPropsKey ? inject(injectExtraPropsKey, () => ({})) : {},
};
},
data() {
this.store = this.storeContext.store;
this.preProps = { ...getOptionProps(this), ...this.injectExtraProps };
watchEffect(() => {
if (mapStateToProps && mapStateToProps.length === 2) {
this.subscribed = finalMapStateToProps(this.store.getState(), {
...this.$props,
...this.injectExtraProps,
});
}
});
return {
subscribed: finalMapStateToProps(this.store.getState(), {
...this.$props,
...this.injectExtraProps,
}),
};
},
mounted() {
this.trySubscribe();
},
beforeUnmount() {
this.tryUnsubscribe();
},
methods: {
handleChange() {
if (!this.unsubscribe) {
return;
}
const props = { ...getOptionProps(this), ...this.injectExtraProps };
const nextSubscribed = finalMapStateToProps(this.store.getState(), props);
if (
!shallowEqual(this.preProps, props) ||
!shallowEqual(this.subscribed, nextSubscribed)
) {
this.subscribed = nextSubscribed;
}
},
trySubscribe() {
if (shouldSubscribe) {
this.unsubscribe = this.store.subscribe(this.handleChange);
this.handleChange();
}
},
tryUnsubscribe() {
if (this.unsubscribe) {
this.unsubscribe();
this.unsubscribe = null;
}
},
getWrappedInstance() {
return this.$refs.wrappedInstance;
},
},
render() {
const { $slots = {}, subscribed, store, $attrs } = this;
const props = { ...getOptionProps(this), ...this.injectExtraProps };
this.preProps = { ...props };
const wrapProps = {
...$attrs,
...props,
...subscribed,
store,
ref: 'wrappedInstance',
};
// const slots = {};
// for (let [key, value] of Object.entries($slots)) {
// slots[key] = () => value();
// }
return createVNode(WrappedComponent, wrapProps, $slots);
},
};
return defineComponent(Connect);
};
}

View File

@ -1,30 +0,0 @@
export default function create(initialState) {
let state = initialState;
const listeners = [];
function setState(partial) {
state = { ...state, ...partial };
for (let i = 0; i < listeners.length; i++) {
listeners[i]();
}
}
function getState() {
return state;
}
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
return {
setState,
getState,
subscribe,
};
}

View File

@ -1,5 +0,0 @@
export { default as Provider } from './Provider';
export { default as connect } from './connect';
export { default as create } from './create';

View File

@ -1,4 +1,4 @@
import { defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import Checkbox from '../checkbox'; import Checkbox from '../checkbox';
import Radio from '../radio'; import Radio from '../radio';
import { SelectionBoxProps } from './interface'; import { SelectionBoxProps } from './interface';
@ -11,52 +11,21 @@ export default defineComponent({
inheritAttrs: false, inheritAttrs: false,
props: SelectionBoxProps, props: SelectionBoxProps,
setup() { setup(props) {
return { return {
unsubscribe: null, checked: computed(() => {
const { store, defaultSelection, rowIndex } = props;
let checked = false;
if (store.selectionDirty) {
checked = store.selectedRowKeys.indexOf(rowIndex) >= 0;
} else {
checked =
store.selectedRowKeys.indexOf(rowIndex) >= 0 || defaultSelection.indexOf(rowIndex) >= 0;
}
return checked;
}),
}; };
}, },
data() {
return {
checked: false,
};
},
created() {
this.checked = this.getCheckState(this.$props);
},
mounted() {
this.subscribe();
},
beforeUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
},
methods: {
getCheckState(props): boolean {
const { store, defaultSelection, rowIndex } = props;
let checked = false;
if (store.getState().selectionDirty) {
checked = store.getState().selectedRowKeys.indexOf(rowIndex) >= 0;
} else {
checked =
store.getState().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() { render() {
const { type, rowIndex, ...rest } = { ...getOptionProps(this), ...this.$attrs } as any; const { type, rowIndex, ...rest } = { ...getOptionProps(this), ...this.$attrs } as any;
const { checked } = this; const { checked } = this;

View File

@ -5,7 +5,7 @@ import Menu from '../menu';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { SelectionCheckboxAllProps } from './interface'; import { SelectionCheckboxAllProps } from './interface';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
function checkSelection({ function checkSelection({
store, store,
@ -17,7 +17,7 @@ function checkSelection({
}) { }) {
return byDefaultChecked return byDefaultChecked
? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked) ? 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) { function getIndeterminateState(props) {
@ -53,7 +53,7 @@ function getIndeterminateState(props) {
byDefaultChecked: true, byDefaultChecked: true,
}); });
if (store.getState().selectionDirty) { if (store.selectionDirty) {
return someCheckedNotByDefaultChecked; return someCheckedNotByDefaultChecked;
} }
return someCheckedNotByDefaultChecked || someCheckedByDefaultChecked; return someCheckedNotByDefaultChecked || someCheckedByDefaultChecked;
@ -64,7 +64,7 @@ function getCheckState(props) {
if (!data.length) { if (!data.length) {
return false; return false;
} }
if (store.getState().selectionDirty) { if (store.selectionDirty) {
return checkSelection({ return checkSelection({
...props, ...props,
data, data,
@ -94,28 +94,17 @@ export default defineComponent({
inheritAttrs: false, inheritAttrs: false,
props: SelectionCheckboxAllProps, props: SelectionCheckboxAllProps,
setup() { setup(props) {
return { return {
defaultSelections: [], defaultSelections: [],
unsubscribe: null, checked: computed(() => {
return getCheckState(props);
}),
indeterminate: computed(() => {
return getIndeterminateState(props);
}),
}; };
}, },
data() {
const { $props: props } = this;
return {
checked: getCheckState(props),
indeterminate: getIndeterminateState(props),
};
},
watch: {
propsSymbol: {
handler() {
this.setCheckState(this.$props);
},
},
},
created() { created() {
const { $props: props } = this; const { $props: props } = this;
@ -132,55 +121,11 @@ export default defineComponent({
}, },
]; ];
}, },
mounted() {
this.subscribe();
},
beforeUnmount() {
if (this.unsubscribe) {
this.unsubscribe();
}
},
methods: { methods: {
checkSelection(props, data, type, byDefaultChecked) {
const { store, getCheckboxPropsByItem, getRecordKey } = props || this.$props;
// type should be 'every' | 'some'
if (type === 'every' || type === 'some') {
return byDefaultChecked
? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked)
: data[type](
(item, i) => store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0,
);
}
return false;
},
setCheckState(props) {
const checked = getCheckState(props);
const indeterminate = getIndeterminateState(props);
this.setState(prevState => {
const newState: any = {};
if (indeterminate !== prevState.indeterminate) {
newState.indeterminate = indeterminate;
}
if (checked !== prevState.checked) {
newState.checked = checked;
}
return newState;
});
},
handleSelectAllChange(e) { handleSelectAllChange(e) {
const { checked } = e.target; const { checked } = e.target;
this.$emit('select', checked ? 'all' : 'removeAll', 0, null); this.$emit('select', checked ? 'all' : 'removeAll', 0, null);
}, },
subscribe() {
const { store } = this;
this.unsubscribe = store.subscribe(() => {
this.setCheckState(this.$props);
});
},
renderMenus(selections) { renderMenus(selections) {
return selections.map((selection, index) => { return selections.map((selection, index) => {

View File

@ -1,11 +1,10 @@
import { defineComponent, inject, markRaw } from 'vue'; import { defineComponent, inject, markRaw, reactive } from 'vue';
import CaretUpFilled from '@ant-design/icons-vue/CaretUpFilled'; import CaretUpFilled from '@ant-design/icons-vue/CaretUpFilled';
import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled'; import CaretDownFilled from '@ant-design/icons-vue/CaretDownFilled';
import VcTable, { INTERNAL_COL_DEFINE } from '../vc-table'; import VcTable, { INTERNAL_COL_DEFINE } from '../vc-table';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import shallowEqual from '../_util/shallowequal'; import shallowEqual from '../_util/shallowequal';
import FilterDropdown from './filterDropdown'; import FilterDropdown from './filterDropdown';
import createStore from './createStore';
import SelectionBox from './SelectionBox'; import SelectionBox from './SelectionBox';
import SelectionCheckboxAll from './SelectionCheckboxAll'; import SelectionCheckboxAll from './SelectionCheckboxAll';
import Column from './Column'; import Column from './Column';
@ -140,11 +139,15 @@ export default defineComponent({
ColumnGroup, ColumnGroup,
props: defaultTableProps, props: defaultTableProps,
setup() { setup(props) {
const store = reactive({
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
selectionDirty: false,
});
return { return {
vcTable: null, vcTable: null,
checkboxPropsCache: {}, checkboxPropsCache: {},
store: null, store,
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
}; };
}, },
@ -189,26 +192,20 @@ export default defineComponent({
rowSelection: { rowSelection: {
handler(val, oldVal) { handler(val, oldVal) {
if (val && 'selectedRowKeys' in val) { if (val && 'selectedRowKeys' in val) {
this.store.setState({ this.store.selectedRowKeys = val.selectedRowKeys || [];
selectedRowKeys: val.selectedRowKeys || [],
});
const { rowSelection } = this; const { rowSelection } = this;
if (rowSelection && val.getCheckboxProps !== rowSelection.getCheckboxProps) { if (rowSelection && val.getCheckboxProps !== rowSelection.getCheckboxProps) {
this.checkboxPropsCache = {}; this.checkboxPropsCache = {};
} }
} else if (oldVal && !val) { } else if (oldVal && !val) {
this.store.setState({ this.store.selectedRowKeys = [];
selectedRowKeys: [],
});
} }
}, },
deep: true, deep: true,
}, },
dataSource() { dataSource() {
this.store.setState({ this.store.selectionDirty = false;
selectionDirty: false,
});
this.checkboxPropsCache = {}; this.checkboxPropsCache = {};
}, },
@ -235,13 +232,6 @@ export default defineComponent({
deep: true, deep: true,
}, },
}, },
created() {
const props = getOptionProps(this);
this.store = createStore({
selectedRowKeys: getRowSelection(props).selectedRowKeys || [],
selectionDirty: false,
});
},
updated() { updated() {
const { columns, sSortColumn: sortColumn, sSortOrder: sortOrder } = this; const { columns, sSortColumn: sortColumn, sSortOrder: sortOrder } = this;
if (this.getSortOrderColumns(columns).length > 0) { if (this.getSortOrderColumns(columns).length > 0) {
@ -470,7 +460,7 @@ export default defineComponent({
const { selectWay, record, checked, changeRowKeys, nativeEvent } = selectionInfo; const { selectWay, record, checked, changeRowKeys, nativeEvent } = selectionInfo;
const rowSelection = getRowSelection(this.$props); const rowSelection = getRowSelection(this.$props);
if (rowSelection && !('selectedRowKeys' in rowSelection)) { if (rowSelection && !('selectedRowKeys' in rowSelection)) {
this.store.setState({ selectedRowKeys }); this.store.selectedRowKeys = selectedRowKeys;
} }
const data = this.getFlatData(); const data = this.getFlatData();
if (!rowSelection.onChange && !rowSelection[selectWay]) { if (!rowSelection.onChange && !rowSelection[selectWay]) {
@ -583,9 +573,7 @@ export default defineComponent({
this.setState(newState, () => { this.setState(newState, () => {
this.scrollToFirstRow(); this.scrollToFirstRow();
this.store.setState({ this.store.selectionDirty = false;
selectionDirty: false,
});
this.$emit( this.$emit(
'change', 'change',
...this.prepareParamsArguments({ ...this.prepareParamsArguments({
@ -601,10 +589,8 @@ export default defineComponent({
handleSelect(record, rowIndex, e) { handleSelect(record, rowIndex, e) {
const checked = e.target.checked; const checked = e.target.checked;
const nativeEvent = e.nativeEvent; const nativeEvent = e.nativeEvent;
const defaultSelection = this.store.getState().selectionDirty const defaultSelection = this.store.selectionDirty ? [] : this.getDefaultSelection();
? [] let selectedRowKeys = this.store.selectedRowKeys.concat(defaultSelection);
: this.getDefaultSelection();
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const key = this.getRecordKey(record, rowIndex); const key = this.getRecordKey(record, rowIndex);
const { pivot } = this.$data; const { pivot } = this.$data;
const rows = this.getFlatCurrentPageData(); const rows = this.getFlatCurrentPageData();
@ -637,9 +623,7 @@ export default defineComponent({
} }
this.setState({ pivot: realIndex }); this.setState({ pivot: realIndex });
this.store.setState({ this.store.selectionDirty = true;
selectionDirty: true,
});
this.setSelectedRowKeys(selectedRowKeys, { this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelectMultiple', selectWay: 'onSelectMultiple',
record, record,
@ -654,9 +638,7 @@ export default defineComponent({
selectedRowKeys = selectedRowKeys.filter(i => key !== i); selectedRowKeys = selectedRowKeys.filter(i => key !== i);
} }
this.setState({ pivot: realIndex }); this.setState({ pivot: realIndex });
this.store.setState({ this.store.selectionDirty = true;
selectionDirty: true,
});
this.setSelectedRowKeys(selectedRowKeys, { this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelect', selectWay: 'onSelect',
record, record,
@ -672,9 +654,7 @@ export default defineComponent({
const nativeEvent = e.nativeEvent; const nativeEvent = e.nativeEvent;
const key = this.getRecordKey(record, rowIndex); const key = this.getRecordKey(record, rowIndex);
const selectedRowKeys = [key]; const selectedRowKeys = [key];
this.store.setState({ this.store.selectionDirty = true;
selectionDirty: true,
});
this.setSelectedRowKeys(selectedRowKeys, { this.setSelectedRowKeys(selectedRowKeys, {
selectWay: 'onSelect', selectWay: 'onSelect',
record, record,
@ -686,10 +666,8 @@ export default defineComponent({
handleSelectRow(selectionKey, index, onSelectFunc) { handleSelectRow(selectionKey, index, onSelectFunc) {
const data = this.getFlatCurrentPageData(); const data = this.getFlatCurrentPageData();
const defaultSelection = this.store.getState().selectionDirty const defaultSelection = this.store.selectionDirty ? [] : this.getDefaultSelection();
? [] const selectedRowKeys = this.store.selectedRowKeys.concat(defaultSelection);
: this.getDefaultSelection();
const selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
const changeableRowKeys = data const changeableRowKeys = data
.filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled) .filter((item, i) => !this.getCheckboxPropsByItem(item, i).disabled)
.map((item, i) => this.getRecordKey(item, i)); .map((item, i) => this.getRecordKey(item, i));
@ -733,10 +711,7 @@ export default defineComponent({
default: default:
break; break;
} }
this.store.selectionDirty = true;
this.store.setState({
selectionDirty: true,
});
// when select custom selection, callback selections[n].onSelect // when select custom selection, callback selections[n].onSelect
const { rowSelection } = this; const { rowSelection } = this;
let customSelectionStartIndex = 2; let customSelectionStartIndex = 2;
@ -779,9 +754,7 @@ export default defineComponent({
} }
this.setState(newState, this.scrollToFirstRow); this.setState(newState, this.scrollToFirstRow);
this.store.setState({ this.store.selectionDirty = false;
selectionDirty: false,
});
this.$emit( this.$emit(
'change', 'change',
...this.prepareParamsArguments({ ...this.prepareParamsArguments({

View File

@ -1,10 +1,9 @@
import * as Vue from 'vue'; import * as Vue from 'vue';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import createStore from '../createStore';
import SelectionBox from '../SelectionBox'; import SelectionBox from '../SelectionBox';
const getDefaultStore = selectedRowKeys => { const getDefaultStore = selectedRowKeys => {
return createStore({ return Vue.reactive({
selectedRowKeys: selectedRowKeys || [], selectedRowKeys: selectedRowKeys || [],
selectionDirty: false, selectionDirty: false,
}); });
@ -26,7 +25,7 @@ describe('SelectionBox', () => {
sync: false, sync: false,
}); });
expect(wrapper.vm.$data).toEqual({ checked: false }); expect(wrapper.vm.checked).toEqual(false);
}); });
it('checked by selectedRowKeys ', () => { it('checked by selectedRowKeys ', () => {
@ -41,7 +40,7 @@ describe('SelectionBox', () => {
sync: false, sync: false,
}); });
expect(wrapper.vm.$data).toEqual({ checked: true }); expect(wrapper.vm.checked).toEqual(true);
}); });
it('checked by defaultSelection', () => { it('checked by defaultSelection', () => {
@ -55,8 +54,7 @@ describe('SelectionBox', () => {
}, },
sync: false, sync: false,
}); });
expect(wrapper.vm.checked).toEqual(true);
expect(wrapper.vm.$data).toEqual({ checked: true });
}); });
it('checked when store change', () => { it('checked when store change', () => {
@ -72,12 +70,10 @@ describe('SelectionBox', () => {
sync: false, sync: false,
}); });
store.setState({ store.selectedRowKeys = ['1'];
selectedRowKeys: ['1'], store.selectionDirty = true;
selectionDirty: true,
});
expect(wrapper.vm.$data).toEqual({ checked: true }); expect(wrapper.vm.checked).toEqual(true);
}); });
it('passes props to Checkbox', done => { it('passes props to Checkbox', done => {

View File

@ -46,7 +46,7 @@ describe('Table.rowSelection', () => {
checkboxAll.element.checked = true; checkboxAll.element.checked = true;
checkboxAll.trigger('change'); checkboxAll.trigger('change');
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0, 1, 2, 3], selectedRowKeys: [0, 1, 2, 3],
selectionDirty: true, selectionDirty: true,
}); });
@ -54,7 +54,7 @@ describe('Table.rowSelection', () => {
checkboxes[1].element.checked = false; checkboxes[1].element.checked = false;
checkboxes[1].trigger('change'); checkboxes[1].trigger('change');
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1, 2, 3], selectedRowKeys: [1, 2, 3],
selectionDirty: true, selectionDirty: true,
}); });
@ -62,7 +62,7 @@ describe('Table.rowSelection', () => {
checkboxes[1].element.checked = true; checkboxes[1].element.checked = true;
checkboxes[1].trigger('change'); checkboxes[1].trigger('change');
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1, 2, 3, 0], selectedRowKeys: [1, 2, 3, 0],
selectionDirty: true, selectionDirty: true,
}); });
@ -77,7 +77,7 @@ describe('Table.rowSelection', () => {
radios[0].element.checked = true; radios[0].element.checked = true;
radios[0].trigger('change'); radios[0].trigger('change');
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0], selectedRowKeys: [0],
selectionDirty: true, selectionDirty: true,
}); });
@ -85,7 +85,7 @@ describe('Table.rowSelection', () => {
radios[radios.length - 1].element.checked = true; radios[radios.length - 1].element.checked = true;
radios[radios.length - 1].trigger('change'); radios[radios.length - 1].trigger('change');
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [3], selectedRowKeys: [3],
selectionDirty: true, selectionDirty: true,
}); });
@ -163,14 +163,14 @@ describe('Table.rowSelection', () => {
it('can be controlled', async () => { it('can be controlled', async () => {
const wrapper = mount(Table, getTableOptions({ rowSelection: { selectedRowKeys: [0] } })); const wrapper = mount(Table, getTableOptions({ rowSelection: { selectedRowKeys: [0] } }));
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [0], selectedRowKeys: [0],
selectionDirty: false, selectionDirty: false,
}); });
wrapper.setProps({ rowSelection: { selectedRowKeys: [1] } }); wrapper.setProps({ rowSelection: { selectedRowKeys: [1] } });
await asyncExpect(() => { await asyncExpect(() => {
expect(getStore(wrapper).getState()).toEqual({ expect(getStore(wrapper)).toEqual({
selectedRowKeys: [1], selectedRowKeys: [1],
selectionDirty: false, selectionDirty: false,
}); });

View File

@ -1,11 +1,10 @@
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import { Store } from './createStore';
import { getSlot } from '../_util/props-util'; import { getSlot } from '../_util/props-util';
import omit from 'omit.js'; import omit from 'omit.js';
const BodyRowProps = { const BodyRowProps = {
store: Store, store: PropTypes.object,
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
}; };
@ -15,40 +14,11 @@ export default function createBodyRow(Component = 'tr') {
name: 'BodyRow', name: 'BodyRow',
inheritAttrs: false, inheritAttrs: false,
props: BodyRowProps, props: BodyRowProps,
setup() { setup(props) {
return { return {
unsubscribe: null, selected: computed(() => props.store?.selectedRowKeys.indexOf(props.rowKey) >= 0),
}; };
}, },
data() {
const { selectedRowKeys } = this.store.getState();
return {
selected: selectedRowKeys.indexOf(this.rowKey) >= 0,
};
},
mounted() {
this.subscribe();
},
beforeUnmount() {
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;
}
});
},
},
render() { render() {
const rowProps = omit({ ...this.$props, ...this.$attrs }, [ const rowProps = omit({ ...this.$props, ...this.$attrs }, [
'prefixCls', 'prefixCls',

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,8 +1,7 @@
import { ExtractPropTypes, PropType } from 'vue'; import { ExtractPropTypes, PropType, UnwrapRef } from 'vue';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes, { withUndefined } from '../_util/vue-types';
import { PaginationProps as getPaginationProps, PaginationConfig } from '../pagination'; import { PaginationProps as getPaginationProps, PaginationConfig } from '../pagination';
import { SpinProps as getSpinProps } from '../spin'; import { SpinProps as getSpinProps } from '../spin';
import { Store } from './createStore';
import { tuple } from '../_util/type'; import { tuple } from '../_util/type';
const PaginationProps = getPaginationProps(); const PaginationProps = getPaginationProps();
@ -196,10 +195,13 @@ export interface TransformCellTextProps {
// text: PropTypes.any, // text: PropTypes.any,
// onSelect: SelectionItemSelectFn; // onSelect: SelectionItemSelectFn;
// } // }
export type TableStore = UnwrapRef<{
selectedRowKeys: any[];
selectionDirty: boolean;
}>;
export const SelectionCheckboxAllProps = { export const SelectionCheckboxAllProps = {
propsSymbol: PropTypes.any, propsSymbol: PropTypes.any,
store: Store, store: PropTypes.any,
locale: PropTypes.any, locale: PropTypes.any,
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
getCheckboxPropsByItem: PropTypes.func, getCheckboxPropsByItem: PropTypes.func,
@ -218,7 +220,7 @@ export const SelectionCheckboxAllProps = {
// } // }
export const SelectionBoxProps = { export const SelectionBoxProps = {
store: Store, store: PropTypes.any,
type: RowSelectionType, type: RowSelectionType,
defaultSelection: PropTypes.array, defaultSelection: PropTypes.array,
rowIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), rowIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

View File

@ -5,7 +5,6 @@ import ColGroup from './ColGroup';
import TableHeader from './TableHeader'; import TableHeader from './TableHeader';
import TableRow from './TableRow'; import TableRow from './TableRow';
import ExpandableRow from './ExpandableRow'; import ExpandableRow from './ExpandableRow';
import { connect } from '../../_util/store';
function noop() {} function noop() {}
const BaseTable = { const BaseTable = {
name: 'BaseTable', name: 'BaseTable',
@ -16,14 +15,14 @@ const BaseTable = {
tableClassName: PropTypes.string.isRequired, tableClassName: PropTypes.string.isRequired,
hasHead: PropTypes.looseBool.isRequired, hasHead: PropTypes.looseBool.isRequired,
hasBody: PropTypes.looseBool.isRequired, hasBody: PropTypes.looseBool.isRequired,
store: PropTypes.object.isRequired,
expander: PropTypes.object.isRequired, expander: PropTypes.object.isRequired,
getRowKey: PropTypes.func, getRowKey: PropTypes.func,
isAnyColumnsFixed: PropTypes.looseBool, isAnyColumnsFixed: PropTypes.looseBool,
}, },
setup() { setup() {
return { return {
table: inject('table', {}), table: inject('table', () => ({})),
store: inject('table-store', () => ({})),
}; };
}, },
methods: { methods: {
@ -40,9 +39,7 @@ const BaseTable = {
})); }));
}, },
handleRowHover(isHover, key) { handleRowHover(isHover, key) {
this.store.setState({ this.store.currentHoverKey = isHover ? key : null;
currentHoverKey: isHover ? key : null,
});
}, },
renderRows(renderData, indent, ancestorKeys = []) { renderRows(renderData, indent, ancestorKeys = []) {
@ -180,4 +177,4 @@ const BaseTable = {
}, },
}; };
export default connect()(BaseTable); export default BaseTable;

View File

@ -1,8 +1,8 @@
import PropTypes, { withUndefined } from '../../_util/vue-types'; import PropTypes, { withUndefined } from '../../_util/vue-types';
import ExpandIcon from './ExpandIcon'; import ExpandIcon from './ExpandIcon';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import { connect } from '../../_util/store';
import { getSlot } from '../../_util/props-util'; import { getSlot } from '../../_util/props-util';
import { computed, inject } from 'vue';
const ExpandableRow = { const ExpandableRow = {
mixins: [BaseMixin], mixins: [BaseMixin],
@ -16,7 +16,6 @@ const ExpandableRow = {
indentSize: PropTypes.number, indentSize: PropTypes.number,
needIndentSpaced: PropTypes.looseBool.isRequired, needIndentSpaced: PropTypes.looseBool.isRequired,
expandRowByClick: PropTypes.looseBool, expandRowByClick: PropTypes.looseBool,
expanded: PropTypes.looseBool.isRequired,
expandIconAsCell: PropTypes.looseBool, expandIconAsCell: PropTypes.looseBool,
expandIconColumnIndex: PropTypes.number, expandIconColumnIndex: PropTypes.number,
childrenColumnName: PropTypes.string, childrenColumnName: PropTypes.string,
@ -26,6 +25,12 @@ const ExpandableRow = {
// onRowClick: PropTypes.func, // onRowClick: PropTypes.func,
// children: PropTypes.func.isRequired, // children: PropTypes.func.isRequired,
}, },
setup(props) {
const store = inject('table-store', () => ({}));
return {
expanded: computed(() => store.expandedRowKeys.includes(props.rowKey)),
};
},
beforeUnmount() { beforeUnmount() {
this.handleDestroy(); this.handleDestroy();
@ -117,6 +122,4 @@ const ExpandableRow = {
}, },
}; };
export default connect(({ expandedRowKeys }, { rowKey }) => ({ export default ExpandableRow;
expanded: expandedRowKeys.includes(rowKey),
}))(ExpandableRow);

View File

@ -1,10 +1,10 @@
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import { connect } from '../../_util/store';
import shallowEqual from '../../_util/shallowequal'; import shallowEqual from '../../_util/shallowequal';
import TableRow from './TableRow'; import TableRow from './TableRow';
import { remove } from './utils'; import { remove } from './utils';
import { initDefaultProps, getOptionProps, getSlot } from '../../_util/props-util'; import { initDefaultProps, getOptionProps, getSlot } from '../../_util/props-util';
import { inject } from 'vue';
export const ExpandableTableProps = () => ({ export const ExpandableTableProps = () => ({
expandIconAsCell: PropTypes.looseBool, expandIconAsCell: PropTypes.looseBool,
@ -21,7 +21,6 @@ export const ExpandableTableProps = () => ({
// onExpand: PropTypes.func, // onExpand: PropTypes.func,
// onExpandedRowsChange: PropTypes.func, // onExpandedRowsChange: PropTypes.func,
columnManager: PropTypes.object.isRequired, columnManager: PropTypes.object.isRequired,
store: PropTypes.object.isRequired,
prefixCls: PropTypes.string.isRequired, prefixCls: PropTypes.string.isRequired,
data: PropTypes.array, data: PropTypes.array,
getRowKey: PropTypes.func, getRowKey: PropTypes.func,
@ -40,8 +39,8 @@ const ExpandableTable = {
childrenColumnName: 'children', childrenColumnName: 'children',
indentSize: 15, indentSize: 15,
}), }),
setup(props) {
data() { const store = inject('table-store', () => ({}));
const { const {
data, data,
childrenColumnName, childrenColumnName,
@ -49,7 +48,7 @@ const ExpandableTable = {
expandedRowKeys, expandedRowKeys,
defaultExpandedRowKeys, defaultExpandedRowKeys,
getRowKey, getRowKey,
} = this; } = props;
let finalExpandedRowKeys = []; let finalExpandedRowKeys = [];
let rows = [...data]; let rows = [...data];
@ -63,15 +62,11 @@ const ExpandableTable = {
} else { } else {
finalExpandedRowKeys = expandedRowKeys || defaultExpandedRowKeys; finalExpandedRowKeys = expandedRowKeys || defaultExpandedRowKeys;
} }
Object.assign(store, {
// this.columnManager = props.columnManager
// this.store = props.store
this.store.setState({
expandedRowsHeight: {}, expandedRowsHeight: {},
expandedRowKeys: finalExpandedRowKeys, expandedRowKeys: finalExpandedRowKeys,
}); });
return {}; return { store };
}, },
mounted() { mounted() {
this.handleUpdated(); this.handleUpdated();
@ -82,9 +77,7 @@ const ExpandableTable = {
watch: { watch: {
expandedRowKeys(val) { expandedRowKeys(val) {
this.$nextTick(() => { this.$nextTick(() => {
this.store.setState({ this.store.expandedRowKeys = val;
expandedRowKeys: val,
});
}); });
}, },
}, },
@ -99,7 +92,7 @@ const ExpandableTable = {
event.stopPropagation(); event.stopPropagation();
} }
let { expandedRowKeys } = this.store.getState(); let { expandedRowKeys } = this.store;
if (expanded) { if (expanded) {
// row was expaned // row was expaned
@ -113,7 +106,7 @@ const ExpandableTable = {
} }
if (!this.expandedRowKeys) { if (!this.expandedRowKeys) {
this.store.setState({ expandedRowKeys }); this.store.expandedRowKeys = expandedRowKeys;
} }
// De-dup of repeat call // De-dup of repeat call
if (!this.latestExpandedRows || !shallowEqual(this.latestExpandedRows, expandedRowKeys)) { if (!this.latestExpandedRows || !shallowEqual(this.latestExpandedRows, expandedRowKeys)) {
@ -164,7 +157,7 @@ const ExpandableTable = {
{ {
key: 'extra-row', key: 'extra-row',
customRender: () => { customRender: () => {
const { expandedRowKeys } = this.store.getState(); const { expandedRowKeys } = this.store;
const expanded = expandedRowKeys.includes(parentKey); const expanded = expandedRowKeys.includes(parentKey);
return { return {
props: { colSpan: colCount }, props: { colSpan: colCount },
@ -245,4 +238,4 @@ const ExpandableTable = {
}, },
}; };
export default connect()(ExpandableTable); export default ExpandableTable;

View File

@ -1,5 +1,5 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import { provide, markRaw, defineComponent, nextTick } from 'vue'; import { provide, markRaw, defineComponent, nextTick, reactive } from 'vue';
import shallowequal from '../../_util/shallowequal'; import shallowequal from '../../_util/shallowequal';
import merge from 'lodash-es/merge'; import merge from 'lodash-es/merge';
import classes from '../../_util/component-classes'; import classes from '../../_util/component-classes';
@ -8,7 +8,6 @@ import PropTypes from '../../_util/vue-types';
import { debounce, getDataAndAriaProps } from './utils'; import { debounce, getDataAndAriaProps } from './utils';
import warning from '../../_util/warning'; import warning from '../../_util/warning';
import addEventListener from '../../vc-util/Dom/addEventListener'; import addEventListener from '../../vc-util/Dom/addEventListener';
import { Provider, create } from '../../_util/store';
import ColumnManager from './ColumnManager'; import ColumnManager from './ColumnManager';
import HeadTable from './HeadTable'; import HeadTable from './HeadTable';
import BodyTable from './BodyTable'; import BodyTable from './BodyTable';
@ -85,6 +84,19 @@ export default defineComponent({
customHeaderRow: () => {}, customHeaderRow: () => {},
}, },
), ),
setup() {
const store = reactive({
currentHoverKey: null,
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: {},
expandedRowsHeight: {},
expandedRowKeys: [],
});
provide('table-store', store);
return {
store,
};
},
data() { data() {
this.preData = [...this.data]; this.preData = [...this.data];
return { return {
@ -146,11 +158,6 @@ export default defineComponent({
} }
}, },
}, },
// static childContextTypes = {
// table: PropTypes.any,
// components: PropTypes.any,
// },
created() { created() {
provide('table', this); provide('table', this);
// ['rowClick', 'rowDoubleclick', 'rowContextmenu', 'rowMouseenter', 'rowMouseleave'].forEach( // ['rowClick', 'rowDoubleclick', 'rowContextmenu', 'rowMouseenter', 'rowMouseleave'].forEach(
@ -169,12 +176,6 @@ export default defineComponent({
// this.columnManager = new ColumnManager(this.columns, this.$slots.default) // this.columnManager = new ColumnManager(this.columns, this.$slots.default)
this.store = create({
currentHoverKey: null,
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: {},
});
this.setScrollPosition('left'); this.setScrollPosition('left');
this.debouncedWindowResize = debounce(this.handleWindowResize, 150); this.debouncedWindowResize = debounce(this.handleWindowResize, 150);
@ -299,10 +300,12 @@ export default defineComponent({
? this.ref_headTable.querySelectorAll('thead') ? this.ref_headTable.querySelectorAll('thead')
: this.ref_bodyTable.querySelectorAll('thead'); : this.ref_bodyTable.querySelectorAll('thead');
const bodyRows = this.ref_bodyTable.querySelectorAll(`.${prefixCls}-row`) || []; const bodyRows = this.ref_bodyTable.querySelectorAll(`.${prefixCls}-row`) || [];
const fixedColumnsHeadRowsHeight = [].map.call(headRows, row => const fixedColumnsHeadRowsHeight = [].map.call(headRows, row => {
row.getBoundingClientRect().height ? row.getBoundingClientRect().height - 0.5 : 'auto', return row.getBoundingClientRect().height
); ? row.getBoundingClientRect().height - 0.5
const state = this.store.getState(); : 'auto';
});
const state = this.store;
const fixedColumnsBodyRowsHeight = [].reduce.call( const fixedColumnsBodyRowsHeight = [].reduce.call(
bodyRows, bodyRows,
(acc, row) => { (acc, row) => {
@ -322,10 +325,8 @@ export default defineComponent({
) { ) {
return; return;
} }
this.store.setState({ this.store.fixedColumnsHeadRowsHeight = fixedColumnsHeadRowsHeight;
fixedColumnsHeadRowsHeight, this.store.fixedColumnsBodyRowsHeight = fixedColumnsBodyRowsHeight;
fixedColumnsBodyRowsHeight,
});
}, },
resetScrollX() { resetScrollX() {
@ -343,10 +344,6 @@ export default defineComponent({
}, },
handleBodyScrollLeft(e) { handleBodyScrollLeft(e) {
// Fix https://github.com/ant-design/ant-design/issues/7635
if (e.currentTarget !== e.target) {
return;
}
const target = e.target; const target = e.target;
const { scroll = {} } = this; const { scroll = {} } = this;
const { ref_headTable, ref_bodyTable } = this; const { ref_headTable, ref_bodyTable } = this;
@ -566,32 +563,30 @@ export default defineComponent({
getRowKey, getRowKey,
}; };
return ( return (
<Provider store={this.store}> <ExpandableTable
<ExpandableTable {...expandableTableProps}
{...expandableTableProps} v-slots={{
v-slots={{ default: expander => {
default: expander => { this.expander = expander;
this.expander = expander; return (
return ( <div
<div ref={this.saveTableNodeRef}
ref={this.saveTableNodeRef} class={tableClassName}
class={tableClassName} style={props.style}
style={props.style} id={props.id}
id={props.id} {...dataAndAriaProps}
{...dataAndAriaProps} >
> {this.renderTitle()}
{this.renderTitle()} <div class={`${prefixCls}-content`}>
<div class={`${prefixCls}-content`}> {this.renderMainTable()}
{this.renderMainTable()} {hasLeftFixed && this.renderLeftFixedTable()}
{hasLeftFixed && this.renderLeftFixedTable()} {hasRightFixed && this.renderRightFixedTable()}
{hasRightFixed && this.renderRightFixedTable()}
</div>
</div> </div>
); </div>
}, );
}} },
/> }}
</Provider> />
); );
}, },
}); });

View File

@ -1,6 +1,6 @@
import classNames from '../../_util/classNames'; import classNames from '../../_util/classNames';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { connect } from '../../_util/store'; import { computed, inject } from 'vue';
const TableHeaderRow = { const TableHeaderRow = {
name: 'TableHeaderRow', name: 'TableHeaderRow',
@ -12,10 +12,31 @@ const TableHeaderRow = {
rows: PropTypes.array, rows: PropTypes.array,
row: PropTypes.array, row: PropTypes.array,
components: PropTypes.object, components: PropTypes.object,
height: PropTypes.any,
customHeaderRow: PropTypes.func, customHeaderRow: PropTypes.func,
prefixCls: PropTypes.prefixCls, prefixCls: PropTypes.prefixCls,
}, },
setup(props) {
const store = inject('table-store', () => ({}));
return {
height: computed(() => {
const { fixedColumnsHeadRowsHeight } = store;
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;
}),
};
},
render() { render() {
const { row, index, height, components, customHeaderRow, prefixCls } = this; const { row, index, height, components, customHeaderRow, prefixCls } = this;
const HeaderRow = components.header.row; const HeaderRow = components.header.row;
@ -67,26 +88,4 @@ const TableHeaderRow = {
}, },
}; };
function getRowHeight(state, props) { export default TableHeaderRow;
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);

View File

@ -1,10 +1,10 @@
import classNames from '../../_util/classNames'; import classNames from '../../_util/classNames';
import PropTypes, { withUndefined } from '../../_util/vue-types'; import PropTypes, { withUndefined } from '../../_util/vue-types';
import { connect } from '../../_util/store';
import TableCell from './TableCell'; import TableCell from './TableCell';
import { initDefaultProps, findDOMNode } from '../../_util/props-util'; import { initDefaultProps, findDOMNode } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import warning from '../../_util/warning'; import warning from '../../_util/warning';
import { computed, inject } from 'vue';
function noop() {} function noop() {}
const TableRow = { const TableRow = {
name: 'TableRow', name: 'TableRow',
@ -22,16 +22,12 @@ const TableRow = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
// onHover: PropTypes.func, // onHover: PropTypes.func,
columns: PropTypes.array, columns: PropTypes.array,
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
index: PropTypes.number, index: PropTypes.number,
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
className: PropTypes.string, className: PropTypes.string,
indent: PropTypes.number, indent: PropTypes.number,
indentSize: PropTypes.number, indentSize: PropTypes.number,
hasExpandIcon: PropTypes.func, hasExpandIcon: PropTypes.func,
hovered: PropTypes.looseBool.isRequired,
visible: PropTypes.looseBool.isRequired,
store: PropTypes.object.isRequired,
fixed: withUndefined(PropTypes.oneOfType([PropTypes.string, PropTypes.looseBool])), fixed: withUndefined(PropTypes.oneOfType([PropTypes.string, PropTypes.looseBool])),
renderExpandIcon: PropTypes.func, renderExpandIcon: PropTypes.func,
renderExpandIconCell: PropTypes.func, renderExpandIconCell: PropTypes.func,
@ -54,8 +50,45 @@ const TableRow = {
}, },
), ),
setup(props) {
const store = inject('table-store', () => ({}));
const visible = computed(() => {
const { expandedRowKeys } = store;
const { ancestorKeys } = props;
return !!(ancestorKeys.length === 0 || ancestorKeys.every(k => expandedRowKeys.includes(k)));
});
const height = computed(() => {
const { expandedRowsHeight, fixedColumnsBodyRowsHeight } = store;
const { fixed, rowKey } = props;
if (!fixed) {
return null;
}
if (expandedRowsHeight[rowKey]) {
return expandedRowsHeight[rowKey];
}
if (fixedColumnsBodyRowsHeight[rowKey]) {
return fixedColumnsBodyRowsHeight[rowKey];
}
return null;
});
const hovered = computed(() => {
const { currentHoverKey } = store;
const { rowKey } = props;
return currentHoverKey === rowKey;
});
return {
store,
visible,
hovered,
height,
};
},
data() { data() {
// this.shouldRender = this.visible
this.rowRef = null; this.rowRef = null;
return { return {
shouldRender: this.visible, shouldRender: this.visible,
@ -119,25 +152,23 @@ const TableRow = {
setExpandedRowHeight() { setExpandedRowHeight() {
const { store, rowKey } = this; const { store, rowKey } = this;
let { expandedRowsHeight } = store.getState(); let { expandedRowsHeight } = store;
const height = this.rowRef.getBoundingClientRect().height; const height = this.rowRef.getBoundingClientRect().height;
expandedRowsHeight = { expandedRowsHeight = {
...expandedRowsHeight, ...expandedRowsHeight,
[rowKey]: height, [rowKey]: height,
}; };
store.setState({ expandedRowsHeight }); store.expandedRowsHeight = expandedRowsHeight;
}, },
setRowHeight() { setRowHeight() {
const { store, rowKey } = this; const { store, rowKey } = this;
const { fixedColumnsBodyRowsHeight } = store.getState(); const { fixedColumnsBodyRowsHeight } = store;
const height = this.rowRef.getBoundingClientRect().height; const height = this.rowRef.getBoundingClientRect().height;
store.setState({ store.fixedColumnsBodyRowsHeight = {
fixedColumnsBodyRowsHeight: { ...fixedColumnsBodyRowsHeight,
...fixedColumnsBodyRowsHeight, [rowKey]: height,
[rowKey]: height, };
},
});
}, },
getStyle() { getStyle() {
@ -269,33 +300,4 @@ const TableRow = {
}, },
}; };
function getRowHeight(state, props) { export default TableRow;
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);

View File

@ -157,7 +157,7 @@
"pretty-quick": "^2.0.0", "pretty-quick": "^2.0.0",
"prismjs": "^1.20.0", "prismjs": "^1.20.0",
"querystring": "^0.2.0", "querystring": "^0.2.0",
"raw-loader": "^4.0.1", "raw-loader": "^4.0.2",
"reqwest": "^2.0.5", "reqwest": "^2.0.5",
"rimraf": "^3.0.0", "rimraf": "^3.0.0",
"rucksack-css": "^1.0.2", "rucksack-css": "^1.0.2",
@ -187,6 +187,7 @@
"vue-infinite-scroll": "^2.0.2", "vue-infinite-scroll": "^2.0.2",
"vue-jest": "^5.0.0-alpha.3", "vue-jest": "^5.0.0-alpha.3",
"vue-loader": "^16.1.1", "vue-loader": "^16.1.1",
"vue-request": "^1.0.2",
"vue-router": "^4.0.0", "vue-router": "^4.0.0",
"vue-server-renderer": "^2.6.11", "vue-server-renderer": "^2.6.11",
"vue-style-loader": "^4.1.2", "vue-style-loader": "^4.1.2",

2
v2-doc

@ -1 +1 @@
Subproject commit 93f8ec64f669520f7bdd060206422719631220b3 Subproject commit 0468ad3010f71ad6b267c66c4f5e28c89c19d83e

View File

@ -51,16 +51,15 @@ module.exports = {
module: { module: {
rules: [ rules: [
{ {
test: /\.(vue|md)$/, test: /\.md$/,
loader: 'raw-loader',
},
{
test: /\.(vue)$/,
loader: 'vue-loader', loader: 'vue-loader',
exclude: /\.(en-US.md|zh-CN.md)$/,
}, },
{ {
test: /\.(en-US.md|zh-CN.md)$/, test: /\.(ts|tsx)?$/,
use: [{ loader: 'vue-loader' }, { loader: './loader.js' }],
},
{
test: /\.tsx?$/,
use: [ use: [
{ {
loader: 'babel-loader', loader: 'babel-loader',
@ -68,6 +67,11 @@ module.exports = {
}, },
{ {
loader: 'ts-loader', loader: 'ts-loader',
options: {
transpileOnly: true,
appendTsSuffixTo: ['\\.vue$'],
happyPackMode: false,
},
}, },
], ],
exclude: /node_modules/, exclude: /node_modules/,