fix: select keyboard position error

refactor-list
tangjinzhou 2021-06-22 13:26:19 +08:00
parent 656d14fc4e
commit 604372ff2d
5 changed files with 40 additions and 17 deletions

View File

@ -0,0 +1,16 @@
import { Ref, ref, watch } from 'vue';
export default function useMemo<T>(
getValue: () => T,
condition: any[],
shouldUpdate: (prev: any[], next: any[]) => boolean,
) {
const cacheRef: Ref<T> = ref(getValue() as any);
watch(condition, (pre, next) => {
if (shouldUpdate(pre, next)) {
cacheRef.value = getValue();
}
});
return cacheRef;
}

View File

@ -14,6 +14,7 @@ import {
OnActiveValue,
} from './interface';
import { RawValueType, FlattenOptionsType } from './interface/generator';
import useMemo from '../_util/hooks/useMemo';
export interface OptionListProps {
prefixCls: string;
id: string;
@ -78,6 +79,12 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
setup(props) {
const itemPrefixCls = computed(() => `${props.prefixCls}-item`);
const memoFlattenOptions = useMemo(
() => props.flattenOptions,
[() => props.open, () => props.flattenOptions],
(prev, next) => next[0] && prev[1] !== next[1],
);
// =========================== List ===========================
const listRef = createRef();
@ -93,12 +100,12 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
// ========================== Active ==========================
const getEnabledActiveIndex = (index: number, offset = 1) => {
const len = props.flattenOptions.length;
const len = memoFlattenOptions.value.length;
for (let i = 0; i < len; i += 1) {
const current = (index + i * offset + len) % len;
const { group, data } = props.flattenOptions[current];
const { group, data } = memoFlattenOptions.value[current];
if (!group && !(data as OptionData).disabled) {
return current;
}
@ -115,7 +122,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
const info = { source: fromKeyboard ? ('keyboard' as const) : ('mouse' as const) };
// Trigger active event
const flattenItem = props.flattenOptions[index];
const flattenItem = memoFlattenOptions.value[index];
if (!flattenItem) {
props.onActiveValue(null, -1, info);
return;
@ -127,7 +134,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
// Auto active first item when list length or searchValue changed
watch(
computed(() => [props.flattenOptions.length, props.searchValue]),
[() => memoFlattenOptions.value.length, () => props.searchValue],
() => {
setActive(props.defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1);
},
@ -136,11 +143,11 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
// Auto scroll to item position in single mode
watch(
computed(() => props.open),
() => props.open,
() => {
if (!props.multiple && props.open && props.values.size === 1) {
const value = Array.from(props.values)[0];
const index = props.flattenOptions.findIndex(({ data }) => data.value === value);
const index = memoFlattenOptions.value.findIndex(({ data }) => data.value === value);
setActive(index);
scrollIntoView(index);
}
@ -167,7 +174,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
};
function renderItem(index: number) {
const item = props.flattenOptions[index];
const item = memoFlattenOptions.value[index];
if (!item) return null;
const itemData = (item.data || {}) as OptionData;
@ -188,6 +195,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
) : null;
}
return {
memoFlattenOptions,
renderItem,
listRef,
state,
@ -220,7 +228,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
// >>> Select
case KeyCode.ENTER: {
// value
const item = props.flattenOptions[state.activeIndex];
const item = memoFlattenOptions.value[state.activeIndex];
if (item && !item.data.disabled) {
onSelectValue(item.data.value);
} else {
@ -258,6 +266,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
itemPrefixCls,
setActive,
onSelectValue,
memoFlattenOptions,
} = this as any;
const {
id,
@ -265,7 +274,6 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
values,
height,
itemHeight,
flattenOptions,
menuItemSelectedIcon,
notFoundContent,
virtual,
@ -274,7 +282,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
} = this.$props as OptionListProps;
const { activeIndex } = this.state;
// ========================== Render ==========================
if (flattenOptions.length === 0) {
if (memoFlattenOptions.length === 0) {
return (
<div
role="listbox"
@ -296,7 +304,7 @@ const OptionList = defineComponent<OptionListProps, { state?: any }>({
<List
itemKey="key"
ref={listRef}
data={flattenOptions}
data={memoFlattenOptions}
height={height}
itemHeight={itemHeight}
fullHeight={false}

View File

@ -11,7 +11,7 @@ import {
import PropTypes from '../../_util/vue-types';
import { RefObject } from '../../_util/createRef';
import antInput from '../../_util/antInputDirective';
import classNames from 'ant-design-vue/es/_util/classNames';
import classNames from '../../_util/classNames';
interface InputProps {
prefixCls: string;

View File

@ -50,7 +50,7 @@ const SingleSelector = defineComponent<SelectorProps>({
return inputValue;
});
watch(
computed(() => [combobox.value, props.activeValue]),
[combobox, () => props.activeValue],
() => {
if (combobox.value) {
inputChanged.value = false;

View File

@ -397,9 +397,9 @@ export default function generateSelector<
// ============================== Ref ===============================
const selectorDomRef = createRef();
const mergedValue = ref(undefined);
const mergedValue = ref();
watch(
computed(() => [props.value, props.defaultValue]),
() => props.value,
() => {
mergedValue.value = props.value !== undefined ? props.value : props.defaultValue;
},
@ -801,7 +801,7 @@ export default function generateSelector<
// Close dropdown when disabled change
watch(
computed(() => props.disabled),
() => props.disabled,
() => {
if (innerOpen.value && !!props.disabled) {
setInnerOpen(false);
@ -1355,7 +1355,6 @@ export default function generateSelector<
);
},
});
Select.inheritAttrs = false;
Select.props = initDefaultProps(BaseProps(), {});
return Select;
}