Skip to content

Commit

Permalink
⚡️ [select] 移除viewInputValue参数,调整算法
Browse files Browse the repository at this point in the history
  • Loading branch information
higuaifan committed Dec 6, 2022
1 parent 4706c42 commit 3167c85
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 116 deletions.
76 changes: 54 additions & 22 deletions lib/base/select/compositions/useSelectBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* @version v1.0.0
*/
import { SelectProps } from '../index';
import { ref, Slots, h, Ref } from 'vue';
import { computed, h, Slots, toRefs } from 'vue';
import useSelectTools, { type IsSelectOption } from './useSelectTools';
import { notEmpty, isFunction } from '../../../dependents/_utils/tools';
import { isEmpty, notEmpty } from '../../../dependents/_utils/tools';
import useSelect from './useSelect';
import useDialog from '../../../message/dialog/useDialog';
import MInput from '../../input/MInput';
Expand All @@ -22,11 +22,12 @@ export default function useSelectBase<T>(props: Required<SelectProps>,
type SelectOption = IsSelectOption<T>;

const tools = useSelectTools<T>(props);
/**
* @description 视图上input应该显示的值
* 区别`inputValue`是为了在遇到input值一致时,导致视图不更新的问题
*/
const viewInputValue = ref<string>('');

const { placeholder } = toRefs(props);

const selectedValue = computed(() => selectOptions.value.find(el => el.isSelected));
const displayPlaceholder = computed(() => selectedValue.value ?
tools.getInputValue(selectedValue.value.value) : placeholder.value);

const optionMatchValue = (option: T) => {
const value = tools.getModelValue(option);
Expand All @@ -36,16 +37,50 @@ export default function useSelectBase<T>(props: Required<SelectProps>,
return props.modelValue === tools.getModelValue(option);
};

const emitFocus = (value: FocusEvent) => {
emit('focus', value, inputValue);
};
const emitFocus = (value: FocusEvent) => {emit('focus', value, inputValue);};
const emitBlur = () => {
if (!viewInputValue.value) {
emit('update:modelValue', null);
if (selectedValue.value && inputValue.value === tools.getInputValue(selectedValue.value.value)) {
// 如果已经选择过 且输入内容和选择内容一致
return;
}
if (isEmpty(inputValue.value)) {
// 如果为空
emit('update:modelValue', undefined);
return;
}
const filterValueArr = selectOptions.value.filter(el => el.isSelected);
viewInputValue.value = filterValueArr.length ? tools.getInputValue(filterValueArr[0].value) : '';
inputValue.value = '';

// 查找是否存在能匹配的
let foundOption: SelectOption | undefined;
let selectedOptionIndex: number = -1;
selectOptions.value.forEach((option, index) => {
if (option.isSelected) {
selectedOptionIndex = index;
}

if (tools.getInputValue(option.value) === inputValue.value) {
foundOption = option;
option.isSelected = true;
return;
}
option.isSelected = false;
});
// 如果无法匹配
if (!foundOption) {
// 回退上轮结果
if (selectedOptionIndex > -1) {
const option = selectOptions.value[selectedOptionIndex];
option.isSelected = true;
inputValue.value = tools.getInputValue(option.value);
} else {
inputValue.value = '';
emit('update:modelValue', undefined);
return;
}
} else {
emit('update:modelValue', foundOption.value);
}


};

const { visible, closeDialog, toggleDialog, showDialog } = useDialog();
Expand All @@ -56,8 +91,7 @@ export default function useSelectBase<T>(props: Required<SelectProps>,
});
option.isSelected = true;
closeDialog();
inputValue.value = '';
viewInputValue.value = tools.getInputValue(option.value);
inputValue.value = tools.getInputValue(option.value);
emit('update:modelValue', tools.getModelValue(option.value));
emit('select', option.value);
};
Expand All @@ -72,7 +106,6 @@ export default function useSelectBase<T>(props: Required<SelectProps>,
showDialog,
input(inputEvent: HTMLElementEvent<HTMLInputElement>) {
inputValue.value = inputEvent.target.value;
viewInputValue.value = inputEvent.target.value;
},
onClickOption,
getOptionDisplayInfo: option => {
Expand All @@ -95,18 +128,17 @@ export default function useSelectBase<T>(props: Required<SelectProps>,
});
}
const baseOptionsFilter = selectOptions.value.filter(el => el.isSelected);
viewInputValue.value = baseOptionsFilter.length ?
tools.getInputValue(baseOptionsFilter[0].value) : '';
inputValue.value = baseOptionsFilter.length ? tools.getInputValue(baseOptionsFilter[0].value) : '';
};


const selectInputRender = () => h(MInput, {
modelValue: viewInputValue.value,
modelValue: inputValue.value,
onClick: props.disabled ? undefined : toggleDialog,
onBlur,
onInput,
onFocus,
placeholder: props.placeholder,
placeholder: String(displayPlaceholder.value), // todo 优化这个交互
disabled: props.disabled,
readonly: props.inputReadonly
});
Expand Down
29 changes: 5 additions & 24 deletions src/page/Playground.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,4 @@
<template>
<div>多选(options为object[]):{{ value1 }}</div>
<MSelect v-model="value1" :options="options1" :input-readonly="false" input-param="after" option-param="before" value-param="number" multiple>
<template #option>
<div>这是一个插槽</div>
</template>
</MSelect>
<div>多选(options为[]):{{ value2 }}</div>
<MSelect v-model="value2" :options="options2" multiple>
<template #option>
<div>插槽</div>
</template>
</MSelect>
________________________________________________________________________
<div>单选(options为object[]):{{ value3 }}</div>
<MSelect v-model="value3" input-param="after" option-param="before" value-param="number" :options="options3">
<template #option>
<div>插槽</div>
</template>
</MSelect>
<div>单选(options为[]){{ value4 }}</div>
<MSelect v-model="value4" :input-readonly="false" :options="options4" >
</MSelect>
Expand Down Expand Up @@ -47,13 +28,13 @@ const options2 = reactive(["1111", "2222", "3333", "4444"]);
// 单选
const value3 = ref('1');
const options3 = reactive([
{ before: "", after: "", number: "1" },
{ before: "", after: "", number: "2" },
{ before: "", after: "", number: "3" },
{ before: "", after: "", number: "4" },
{ before: "", after: "", number: "111" },
{ before: "", after: "", number: "221" },
{ before: "", after: "", number: "3331" },
{ before: "", after: "", number: "44441" },
]);
const value4 = ref(undefined);
const options4 = reactive(["1", "2", "3", "4"]);
const options4 = reactive(["1111", "2222", "3313", "4441"]);
</script>

<style lang="scss" scoped>
Expand Down
Loading

0 comments on commit 3167c85

Please sign in to comment.