Skip to content

Commit 604372f

Browse files
committed
fix: select keyboard position error
1 parent 656d14f commit 604372f

File tree

5 files changed

+40
-17
lines changed

5 files changed

+40
-17
lines changed

components/_util/hooks/useMemo.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Ref, ref, watch } from 'vue';
2+
3+
export default function useMemo<T>(
4+
getValue: () => T,
5+
condition: any[],
6+
shouldUpdate: (prev: any[], next: any[]) => boolean,
7+
) {
8+
const cacheRef: Ref<T> = ref(getValue() as any);
9+
watch(condition, (pre, next) => {
10+
if (shouldUpdate(pre, next)) {
11+
cacheRef.value = getValue();
12+
}
13+
});
14+
15+
return cacheRef;
16+
}

components/vc-select/OptionList.tsx

+19-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
OnActiveValue,
1515
} from './interface';
1616
import { RawValueType, FlattenOptionsType } from './interface/generator';
17+
import useMemo from '../_util/hooks/useMemo';
1718
export interface OptionListProps {
1819
prefixCls: string;
1920
id: string;
@@ -78,6 +79,12 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
7879
setup(props) {
7980
const itemPrefixCls = computed(() => `${props.prefixCls}-item`);
8081

82+
const memoFlattenOptions = useMemo(
83+
() => props.flattenOptions,
84+
[() => props.open, () => props.flattenOptions],
85+
(prev, next) => next[0] && prev[1] !== next[1],
86+
);
87+
8188
// =========================== List ===========================
8289
const listRef = createRef();
8390

@@ -93,12 +100,12 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
93100

94101
// ========================== Active ==========================
95102
const getEnabledActiveIndex = (index: number, offset = 1) => {
96-
const len = props.flattenOptions.length;
103+
const len = memoFlattenOptions.value.length;
97104

98105
for (let i = 0; i < len; i += 1) {
99106
const current = (index + i * offset + len) % len;
100107

101-
const { group, data } = props.flattenOptions[current];
108+
const { group, data } = memoFlattenOptions.value[current];
102109
if (!group && !(data as OptionData).disabled) {
103110
return current;
104111
}
@@ -115,7 +122,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
115122
const info = { source: fromKeyboard ? ('keyboard' as const) : ('mouse' as const) };
116123

117124
// Trigger active event
118-
const flattenItem = props.flattenOptions[index];
125+
const flattenItem = memoFlattenOptions.value[index];
119126
if (!flattenItem) {
120127
props.onActiveValue(null, -1, info);
121128
return;
@@ -127,7 +134,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
127134
// Auto active first item when list length or searchValue changed
128135

129136
watch(
130-
computed(() => [props.flattenOptions.length, props.searchValue]),
137+
[() => memoFlattenOptions.value.length, () => props.searchValue],
131138
() => {
132139
setActive(props.defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1);
133140
},
@@ -136,11 +143,11 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
136143
// Auto scroll to item position in single mode
137144

138145
watch(
139-
computed(() => props.open),
146+
() => props.open,
140147
() => {
141148
if (!props.multiple && props.open && props.values.size === 1) {
142149
const value = Array.from(props.values)[0];
143-
const index = props.flattenOptions.findIndex(({ data }) => data.value === value);
150+
const index = memoFlattenOptions.value.findIndex(({ data }) => data.value === value);
144151
setActive(index);
145152
scrollIntoView(index);
146153
}
@@ -167,7 +174,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
167174
};
168175

169176
function renderItem(index: number) {
170-
const item = props.flattenOptions[index];
177+
const item = memoFlattenOptions.value[index];
171178
if (!item) return null;
172179

173180
const itemData = (item.data || {}) as OptionData;
@@ -188,6 +195,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
188195
) : null;
189196
}
190197
return {
198+
memoFlattenOptions,
191199
renderItem,
192200
listRef,
193201
state,
@@ -220,7 +228,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
220228
// >>> Select
221229
case KeyCode.ENTER: {
222230
// value
223-
const item = props.flattenOptions[state.activeIndex];
231+
const item = memoFlattenOptions.value[state.activeIndex];
224232
if (item && !item.data.disabled) {
225233
onSelectValue(item.data.value);
226234
} else {
@@ -258,14 +266,14 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
258266
itemPrefixCls,
259267
setActive,
260268
onSelectValue,
269+
memoFlattenOptions,
261270
} = this as any;
262271
const {
263272
id,
264273
childrenAsData,
265274
values,
266275
height,
267276
itemHeight,
268-
flattenOptions,
269277
menuItemSelectedIcon,
270278
notFoundContent,
271279
virtual,
@@ -274,7 +282,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
274282
} = this.$props as OptionListProps;
275283
const { activeIndex } = this.state;
276284
// ========================== Render ==========================
277-
if (flattenOptions.length === 0) {
285+
if (memoFlattenOptions.length === 0) {
278286
return (
279287
<div
280288
role="listbox"
@@ -296,7 +304,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
296304
<List
297305
itemKey="key"
298306
ref={listRef}
299-
data={flattenOptions}
307+
data={memoFlattenOptions}
300308
height={height}
301309
itemHeight={itemHeight}
302310
fullHeight={false}

components/vc-select/Selector/Input.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
import PropTypes from '../../_util/vue-types';
1212
import { RefObject } from '../../_util/createRef';
1313
import antInput from '../../_util/antInputDirective';
14-
import classNames from 'ant-design-vue/es/_util/classNames';
14+
import classNames from '../../_util/classNames';
1515

1616
interface InputProps {
1717
prefixCls: string;

components/vc-select/Selector/SingleSelector.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const SingleSelector = defineComponent<SelectorProps>({
5050
return inputValue;
5151
});
5252
watch(
53-
computed(() => [combobox.value, props.activeValue]),
53+
[combobox, () => props.activeValue],
5454
() => {
5555
if (combobox.value) {
5656
inputChanged.value = false;

components/vc-select/generate.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,9 @@ export default function generateSelector<
397397
// ============================== Ref ===============================
398398
const selectorDomRef = createRef();
399399

400-
const mergedValue = ref(undefined);
400+
const mergedValue = ref();
401401
watch(
402-
computed(() => [props.value, props.defaultValue]),
402+
() => props.value,
403403
() => {
404404
mergedValue.value = props.value !== undefined ? props.value : props.defaultValue;
405405
},
@@ -801,7 +801,7 @@ export default function generateSelector<
801801
// Close dropdown when disabled change
802802

803803
watch(
804-
computed(() => props.disabled),
804+
() => props.disabled,
805805
() => {
806806
if (innerOpen.value && !!props.disabled) {
807807
setInnerOpen(false);
@@ -1355,7 +1355,6 @@ export default function generateSelector<
13551355
);
13561356
},
13571357
});
1358-
Select.inheritAttrs = false;
13591358
Select.props = initDefaultProps(BaseProps(), {});
13601359
return Select;
13611360
}

0 commit comments

Comments
 (0)