Skip to content

Commit 3613ece

Browse files
committed
fix: select deep watch options, close #5398
1 parent e146b48 commit 3613ece

File tree

10 files changed

+92
-88
lines changed

10 files changed

+92
-88
lines changed

components/vc-select/Select.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import { toArray } from './utils/commonUtil';
4242
import useFilterOptions from './hooks/useFilterOptions';
4343
import useCache from './hooks/useCache';
4444
import type { Key, VueNode } from '../_util/type';
45-
import { computed, defineComponent, ref, toRef, watchEffect } from 'vue';
45+
import { computed, defineComponent, ref, shallowRef, toRef, watchEffect } from 'vue';
4646
import type { ExtractPropTypes, PropType } from 'vue';
4747
import PropTypes from '../_util/vue-types';
4848
import { initDefaultProps } from '../_util/props-util';
@@ -314,13 +314,15 @@ export default defineComponent({
314314
};
315315

316316
// Fill tag as option if mode is `tags`
317-
const filledTagOptions = computed(() => {
317+
const filledTagOptions = shallowRef();
318+
watchEffect(() => {
318319
if (props.mode !== 'tags') {
319-
return mergedOptions.value;
320+
filledTagOptions.value = mergedOptions.value;
321+
return;
320322
}
321323

322324
// >>> Tag mode
323-
const cloneOptions = [...mergedOptions.value];
325+
const cloneOptions = mergedOptions.value.slice();
324326

325327
// Check if value exist in options (include new patch item)
326328
const existOptions = (val: RawValueType) => valueOptions.value.has(val);
@@ -336,7 +338,7 @@ export default defineComponent({
336338
}
337339
});
338340

339-
return cloneOptions;
341+
filledTagOptions.value = cloneOptions;
340342
});
341343

342344
const filteredOptions = useFilterOptions(

components/vc-select/hooks/useFilterOptions.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import type {
77
BaseOptionType,
88
} from '../Select';
99
import { injectPropsWithOption } from '../utils/valueUtil';
10-
import type { Ref } from 'vue';
11-
import { toRaw, computed } from 'vue';
10+
import type { Ref, ShallowRef } from 'vue';
11+
import { computed } from 'vue';
1212

1313
function includes(test: any, search: string) {
1414
return toArray(test).join('').toUpperCase().includes(search);
1515
}
1616

1717
export default (
18-
options: Ref<DefaultOptionType[]>,
18+
options: ShallowRef<DefaultOptionType[]>,
1919
fieldNames: Ref<FieldNames>,
2020
searchValue?: Ref<string>,
2121
filterOption?: Ref<SelectProps['filterOption']>,
@@ -55,7 +55,7 @@ export default (
5555
? opt => injectPropsWithOption(opt)
5656
: opt => opt;
5757

58-
toRaw(options.value).forEach(item => {
58+
options.value.forEach(item => {
5959
// Group should check child options
6060
if (item[fieldOptions]) {
6161
// Check group first

components/vc-select/hooks/useOptions.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Ref } from 'vue';
2-
import { toRaw, shallowRef, watchEffect } from 'vue';
2+
import { toRaw, shallowRef, watchEffect, watch } from 'vue';
33
import type { FieldNames, RawValueType } from '../Select';
44
import { convertChildrenToData } from '../utils/legacyUtil';
55

@@ -15,13 +15,20 @@ export default function useOptions<OptionType>(
1515
const mergedOptions = shallowRef();
1616
const valueOptions = shallowRef();
1717
const labelOptions = shallowRef();
18+
const tempMergedOptions = shallowRef([]);
19+
watch(
20+
[options, children],
21+
() => {
22+
if (options.value) {
23+
tempMergedOptions.value = toRaw(options.value).slice();
24+
} else {
25+
tempMergedOptions.value = convertChildrenToData(children.value);
26+
}
27+
},
28+
{ immediate: true, deep: true },
29+
);
1830
watchEffect(() => {
19-
let newOptions = toRaw(options.value);
20-
const childrenAsData = !options.value;
21-
22-
if (childrenAsData) {
23-
newOptions = convertChildrenToData(children.value);
24-
}
31+
const newOptions = tempMergedOptions.value;
2532

2633
const newValueOptions = new Map<RawValueType, OptionType>();
2734
const newLabelOptions = new Map<any, OptionType>();

components/vc-tree-select/OptionList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export default defineComponent({
9898
);
9999
const mergedExpandedKeys = computed(() => {
100100
if (legacyContext.treeExpandedKeys) {
101-
return toRaw(legacyContext.treeExpandedKeys).slice();
101+
return legacyContext.treeExpandedKeys.slice();
102102
}
103103
return baseProps.searchValue ? searchExpandedKeys.value : expandedKeys.value;
104104
});

components/vc-tree-select/hooks/useCache.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Ref } from 'vue';
2-
import { toRaw, computed, shallowRef } from 'vue';
2+
import { watch, toRaw, computed, shallowRef } from 'vue';
33
import type { LabeledValueType, RawValueType } from '../TreeSelect';
44

55
/**
@@ -10,12 +10,19 @@ export default (values: Ref<LabeledValueType[]>): [Ref<LabeledValueType[]>] => {
1010
const cacheRef = shallowRef({
1111
valueLabels: new Map<RawValueType, any>(),
1212
});
13-
13+
const mergedValues = shallowRef();
14+
watch(
15+
values,
16+
() => {
17+
mergedValues.value = toRaw(values.value);
18+
},
19+
{ immediate: true },
20+
);
1421
const newFilledValues = computed(() => {
1522
const { valueLabels } = cacheRef.value;
1623
const valueLabelsCache = new Map<RawValueType, any>();
1724

18-
const filledValues = toRaw(values.value).map(item => {
25+
const filledValues = mergedValues.value.map(item => {
1926
const { value } = item;
2027
const mergedLabel = item.label ?? valueLabels.get(value);
2128

components/vc-tree-select/hooks/useCheckedKeys.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import type { DataEntity } from '../../vc-tree/interface';
33
import { conductCheck } from '../../vc-tree/utils/conductUtil';
44
import type { LabeledValueType, RawValueType } from '../TreeSelect';
55
import type { Ref, ShallowRef } from 'vue';
6-
import { toRaw, shallowRef, watchEffect } from 'vue';
6+
import { shallowRef, watchEffect } from 'vue';
77

88
export default (
9-
rawLabeledValues: Ref<LabeledValueType[]>,
10-
rawHalfCheckedValues: Ref<LabeledValueType[]>,
9+
rawLabeledValues: ShallowRef<LabeledValueType[]>,
10+
rawHalfCheckedValues: ShallowRef<LabeledValueType[]>,
1111
treeConduction: Ref<boolean>,
1212
keyEntities: Ref<Record<Key, DataEntity>>,
1313
maxLevel: Ref<number>,
@@ -17,10 +17,8 @@ export default (
1717
const newRawHalfCheckedValues = shallowRef<RawValueType[]>([]);
1818

1919
watchEffect(() => {
20-
let checkedKeys: RawValueType[] = toRaw(rawLabeledValues.value).map(({ value }) => value);
21-
let halfCheckedKeys: RawValueType[] = toRaw(rawHalfCheckedValues.value).map(
22-
({ value }) => value,
23-
);
20+
let checkedKeys: RawValueType[] = rawLabeledValues.value.map(({ value }) => value);
21+
let halfCheckedKeys: RawValueType[] = rawHalfCheckedValues.value.map(({ value }) => value);
2422

2523
const missingValues = checkedKeys.filter(key => !keyEntities.value[key]);
2624

components/vc-tree-select/hooks/useDataEntities.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import type { DataEntity } from '../../vc-tree/interface';
33
import type { FieldNames, RawValueType } from '../TreeSelect';
44

55
import { isNil } from '../utils/valueUtil';
6-
import type { Ref } from 'vue';
7-
import { toRaw, ref, watchEffect } from 'vue';
6+
import type { Ref, ShallowRef } from 'vue';
7+
import { shallowRef, watchEffect } from 'vue';
88
import { warning } from '../../vc-util/warning';
99

10-
export default (treeData: Ref<any>, fieldNames: Ref<FieldNames>) => {
11-
const valueEntities = ref<Map<RawValueType, DataEntity>>(new Map());
12-
const keyEntities = ref<Record<string, DataEntity>>({});
10+
export default (treeData: ShallowRef<any>, fieldNames: Ref<FieldNames>) => {
11+
const valueEntities = shallowRef<Map<RawValueType, DataEntity>>(new Map());
12+
const keyEntities = shallowRef<Record<string, DataEntity>>({});
1313
watchEffect(() => {
1414
const fieldNamesValue = fieldNames.value;
15-
const collection = convertDataToEntities(toRaw(treeData.value), {
15+
const collection = convertDataToEntities(treeData.value, {
1616
fieldNames: fieldNamesValue,
1717
initWrapper: wrapper => ({
1818
...wrapper,

components/vc-tree-select/hooks/useFilterTreeData.ts

+4-20
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import type { Ref } from 'vue';
2-
import { toRaw, computed } from 'vue';
1+
import type { Ref, ShallowRef } from 'vue';
2+
import { computed } from 'vue';
33
import type { DefaultOptionType, InternalFieldName, TreeSelectProps } from '../TreeSelect';
44
import { fillLegacyProps } from '../utils/legacyUtil';
55

66
type GetFuncType<T> = T extends boolean ? never : T;
77
type FilterFn = GetFuncType<TreeSelectProps['filterTreeNode']>;
88

99
export default (
10-
treeData: Ref<DefaultOptionType[]>,
10+
treeData: ShallowRef<DefaultOptionType[]>,
1111
searchValue: Ref<string>,
1212
{
1313
treeNodeFilterProp,
@@ -56,24 +56,8 @@ export default (
5656
}
5757
}
5858
return res;
59-
// return list
60-
// .map(dataNode => {
61-
// const children = dataNode[fieldChildren];
62-
63-
// const match = keepAll || filterOptionFunc(searchValueVal, fillLegacyProps(dataNode));
64-
// const childList = dig(children || [], match);
65-
66-
// if (match || childList.length) {
67-
// return {
68-
// ...dataNode,
69-
// [fieldChildren]: childList,
70-
// };
71-
// }
72-
// return null;
73-
// })
74-
// .filter(node => node);
7559
}
7660

77-
return dig(toRaw(treeData.value));
61+
return dig(treeData.value);
7862
});
7963
};

components/vc-tree-select/hooks/useTreeData.ts

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Ref } from 'vue';
2-
import { toRaw, computed } from 'vue';
1+
import type { Ref, ShallowRef } from 'vue';
2+
import { shallowRef, watch, toRaw } from 'vue';
33
import type { DataNode, SimpleModeConfig } from '../interface';
44
import { convertChildrenToData } from '../utils/legacyUtil';
55
import type { DefaultOptionType } from '../TreeSelect';
@@ -49,20 +49,26 @@ export default function useTreeData(
4949
treeData: Ref<DataNode[]>,
5050
children: Ref<VueNode[]>,
5151
simpleMode: Ref<boolean | SimpleModeConfig>,
52-
): Ref<DefaultOptionType[]> {
53-
return computed(() => {
54-
const simpleModeValue = simpleMode.value;
55-
if (treeData.value) {
56-
return simpleMode.value
57-
? parseSimpleTreeData(toRaw(treeData.value), {
58-
id: 'id',
59-
pId: 'pId',
60-
rootPId: null,
61-
...(simpleModeValue !== true ? simpleModeValue : {}),
62-
})
63-
: treeData.value;
64-
}
65-
66-
return convertChildrenToData(toRaw(children.value));
67-
});
52+
): ShallowRef<DefaultOptionType[]> {
53+
const mergedTreeData = shallowRef<DefaultOptionType[]>();
54+
watch(
55+
[simpleMode, treeData, children],
56+
() => {
57+
const simpleModeValue = simpleMode.value;
58+
if (treeData.value) {
59+
mergedTreeData.value = simpleMode.value
60+
? parseSimpleTreeData(toRaw(treeData.value), {
61+
id: 'id',
62+
pId: 'pId',
63+
rootPId: null,
64+
...(simpleModeValue !== true ? simpleModeValue : {}),
65+
})
66+
: toRaw(treeData.value);
67+
} else {
68+
mergedTreeData.value = convertChildrenToData(toRaw(children.value));
69+
}
70+
},
71+
{ immediate: true, deep: true },
72+
);
73+
return mergedTreeData;
6874
}

components/vc-tree/Tree.tsx

+17-17
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,16 @@ export default defineComponent({
104104
dragOverNodeKey: null,
105105
});
106106
const treeData = shallowRef([]);
107-
watchEffect(() => {
108-
treeData.value =
109-
props.treeData !== undefined
110-
? toRaw(props.treeData)
111-
: convertTreeToData(toRaw(props.children));
112-
});
107+
watch(
108+
[() => props.treeData, () => props.children],
109+
() => {
110+
treeData.value =
111+
props.treeData !== undefined
112+
? toRaw(props.treeData)
113+
: convertTreeToData(toRaw(props.children));
114+
},
115+
{ immediate: true, deep: true },
116+
);
113117
const keyEntities = shallowRef({});
114118

115119
const focused = ref(false);
@@ -143,7 +147,7 @@ export default defineComponent({
143147

144148
watchEffect(() => {
145149
if (treeData.value) {
146-
const entitiesMap = convertDataToEntities(toRaw(treeData.value), {
150+
const entitiesMap = convertDataToEntities(treeData.value, {
147151
fieldNames: fieldNames.value,
148152
});
149153
keyEntities.value = {
@@ -190,19 +194,15 @@ export default defineComponent({
190194
// ================ flattenNodes =================
191195
const flattenNodes = shallowRef([]);
192196
watchEffect(() => {
193-
flattenNodes.value = flattenTreeData(
194-
toRaw(treeData.value),
195-
toRaw(expandedKeys.value),
196-
fieldNames.value,
197-
);
197+
flattenNodes.value = flattenTreeData(treeData.value, expandedKeys.value, fieldNames.value);
198198
});
199199
// ================ selectedKeys =================
200200
watchEffect(() => {
201201
if (props.selectable) {
202202
if (props.selectedKeys !== undefined) {
203-
selectedKeys.value = calcSelectedKeys(toRaw(props.selectedKeys), props);
203+
selectedKeys.value = calcSelectedKeys(props.selectedKeys, props);
204204
} else if (!init && props.defaultSelectedKeys) {
205-
selectedKeys.value = calcSelectedKeys(toRaw(props.defaultSelectedKeys), props);
205+
selectedKeys.value = calcSelectedKeys(props.defaultSelectedKeys, props);
206206
}
207207
}
208208
});
@@ -213,12 +213,12 @@ export default defineComponent({
213213
let checkedKeyEntity;
214214

215215
if (props.checkedKeys !== undefined) {
216-
checkedKeyEntity = parseCheckedKeys(toRaw(props.checkedKeys)) || {};
216+
checkedKeyEntity = parseCheckedKeys(props.checkedKeys) || {};
217217
} else if (!init && props.defaultCheckedKeys) {
218-
checkedKeyEntity = parseCheckedKeys(toRaw(props.defaultCheckedKeys)) || {};
218+
checkedKeyEntity = parseCheckedKeys(props.defaultCheckedKeys) || {};
219219
} else if (treeData.value) {
220220
// If `treeData` changed, we also need check it
221-
checkedKeyEntity = parseCheckedKeys(toRaw(props.checkedKeys)) || {
221+
checkedKeyEntity = parseCheckedKeys(props.checkedKeys) || {
222222
checkedKeys: checkedKeys.value,
223223
halfCheckedKeys: halfCheckedKeys.value,
224224
};

0 commit comments

Comments
 (0)