Skip to content

Commit 9c0fcec

Browse files
daviForevelkagol
authored andcommitted
fix(select): 修复select组件 valueChange 事件的回调参数问题
1 parent 87d4940 commit 9c0fcec

File tree

4 files changed

+59
-20
lines changed

4 files changed

+59
-20
lines changed

packages/devui-vue/devui/select/src/composables/use-option.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default function useOption(props: OptionProps): UseOptionReturnType {
4141

4242
const optionSelect = (): void => {
4343
if (!props.disabled) {
44-
select?.valueChange(optionItem.value, isObjectOption.value);
44+
select?.valueChange(optionItem.value);
4545
}
4646
};
4747

@@ -55,11 +55,11 @@ export default function useOption(props: OptionProps): UseOptionReturnType {
5555
});
5656

5757
onBeforeMount(() => {
58-
select?.updateInjectOptions(optionItem.value, 'add');
58+
select?.updateInjectOptions(optionItem.value, 'add', isObjectOption.value);
5959
});
6060

6161
onBeforeUnmount(() => {
62-
select?.updateInjectOptions(optionItem.value, 'delete');
62+
select?.updateInjectOptions(optionItem.value, 'delete', isObjectOption.value);
6363
});
6464

6565
return {

packages/devui-vue/devui/select/src/select-types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ export interface UseSelectReturnType {
124124
isShowEmptyText: ComputedRef<boolean>;
125125
onClick: (e: MouseEvent) => void;
126126
handleClear: (e: MouseEvent) => void;
127-
valueChange: (item: OptionObjectItem, isObjectOption: boolean) => void;
127+
valueChange: (item: OptionObjectItem) => void;
128128
handleClose: () => void;
129-
updateInjectOptions: (item: Record<string, unknown>, operation: string) => void;
129+
updateInjectOptions: (item: Record<string, unknown>, operation: string, isObject: boolean) => void;
130130
tagDelete: (data: OptionObjectItem) => void;
131131
onFocus: (e: FocusEvent) => void;
132132
onBlur: (e: FocusEvent) => void;
@@ -142,9 +142,9 @@ export interface SelectContext extends SelectProps {
142142
isOpen: boolean;
143143
selectedOptions: OptionObjectItem[];
144144
filterQuery: string;
145-
valueChange: (item: OptionObjectItem, isObjectOption: boolean) => void;
145+
valueChange: (item: OptionObjectItem) => void;
146146
handleClear: () => void;
147-
updateInjectOptions: (item: Record<string, unknown>, operation: string) => void;
147+
updateInjectOptions: (item: Record<string, unknown>, operation: string, isObject: boolean) => void;
148148
tagDelete: (data: OptionObjectItem) => void;
149149
onFocus: (e: FocusEvent) => void;
150150
onBlur: (e: FocusEvent) => void;

packages/devui-vue/devui/select/src/use-select.ts

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default function useSelect(
2222

2323
const selectDisabled = computed(() => formContext?.disabled || props.disabled);
2424
const selectSize = computed(() => formContext?.size || props.size);
25+
const isObjectOption = ref(false);
2526

2627
// 控制弹窗开合
2728
const isOpen = ref<boolean>(false);
@@ -50,6 +51,7 @@ export default function useSelect(
5051
});
5152

5253
// 这里对d-select组件options做统一处理,此options只用作渲染option列表
54+
const cacheOptions = new Map();
5355
const mergeOptions = computed(() => {
5456
const { multiple, modelValue } = props;
5557
return props.options.map((item) => {
@@ -79,20 +81,25 @@ export default function useSelect(
7981
option._checked = false;
8082
}
8183
}
84+
cacheOptions.set(option.value, option);
8285
return option;
8386
});
8487
});
8588

89+
// 缓存options,用value来获取对应的optionItem
90+
const getValuesOption = (values: KeyType<OptionObjectItem, 'value'>[]) => values.map((value) => cacheOptions.get(value));
91+
8692
// 这里处理d-option组件生成的Options
8793
const injectOptions = ref(new Map());
88-
const updateInjectOptions = (item: Record<string, unknown>, operation: string) => {
94+
const updateInjectOptions = (item: Record<string, unknown>, operation: string, isObject: boolean) => {
8995
if (operation === 'add') {
9096
injectOptions.value.set(item.value, item);
9197
} else if (operation === 'delete') {
9298
if (injectOptions.value.get(item.value)) {
9399
injectOptions.value.delete(item.value);
94100
}
95101
}
102+
isObjectOption.value = isObject;
96103
};
97104

98105
const getInjectOptions = (values: KeyType<OptionObjectItem, 'value'>[]) => {
@@ -122,10 +129,10 @@ export default function useSelect(
122129
// 目前看该警告和下拉面板使用Transition也有关
123130
const inputValue = computed<string>(() => {
124131
if (props.multiple && Array.isArray(props.modelValue)) {
125-
selectedOptions.value = getInjectOptions(props.modelValue).filter((item) => !!item);
132+
selectedOptions.value = getInjectOptions(props.modelValue).filter((item) => (item ? true : false));
126133
return selectedOptions.value.map((item) => item?.name || item?.value || '').join(',');
127134
} else if (!Array.isArray(props.modelValue)) {
128-
selectedOptions.value = getInjectOptions([props.modelValue]).filter((item) => !!item);
135+
selectedOptions.value = getInjectOptions([props.modelValue]).filter((item) => (item ? true : false));
129136
return selectedOptions.value[0]?.name || '';
130137
}
131138
return '';
@@ -139,7 +146,31 @@ export default function useSelect(
139146

140147
const isSupportFilter = computed(() => isFunction(props.filter) || (typeof props.filter === 'boolean' && props.filter));
141148

142-
const valueChange = (item: OptionObjectItem, isObjectOption: boolean) => {
149+
const getMultipleSelected = (items: (string | number)[]) => {
150+
if (mergeOptions.value.length) {
151+
ctx.emit(
152+
'value-change',
153+
getValuesOption(items).filter((item) => (item ? true : false))
154+
);
155+
} else if (isObjectOption.value) {
156+
const selectItems = getInjectOptions(items).filter((item) => (item ? true : false));
157+
ctx.emit('value-change', selectItems);
158+
} else {
159+
ctx.emit('value-change', items);
160+
}
161+
};
162+
163+
const getSingleSelected = (item: OptionObjectItem) => {
164+
if (mergeOptions.value.length) {
165+
ctx.emit('value-change', getValuesOption([item.value])[0]);
166+
} else if (isObjectOption.value) {
167+
ctx.emit('value-change', item);
168+
} else {
169+
ctx.emit('value-change', item.value);
170+
}
171+
};
172+
173+
const valueChange = (item: OptionObjectItem) => {
143174
const { multiple } = props;
144175
let { modelValue } = props;
145176
if (multiple) {
@@ -149,6 +180,10 @@ export default function useSelect(
149180
if (option) {
150181
option._checked = !option._checked;
151182
}
183+
const mergeOption = getValuesOption([item.value])[0];
184+
if (mergeOption) {
185+
mergeOption._checked = !mergeOption._checked;
186+
}
152187
if (index > -1) {
153188
checkedItems.splice(index, 1);
154189
} else {
@@ -162,11 +197,12 @@ export default function useSelect(
162197
if (isSupportFilter.value) {
163198
focus();
164199
}
200+
getMultipleSelected(checkedItems);
165201
} else {
166202
ctx.emit('update:modelValue', item.value);
167203
toggleChange(false);
204+
getSingleSelected(item);
168205
}
169-
ctx.emit('value-change', isObjectOption ? item : item.value);
170206
};
171207

172208
const handleClose = () => {
@@ -177,8 +213,10 @@ export default function useSelect(
177213
const handleClear = () => {
178214
if (props.multiple) {
179215
ctx.emit('update:modelValue', []);
216+
ctx.emit('value-change', []);
180217
} else {
181218
ctx.emit('update:modelValue', '');
219+
ctx.emit('value-change', '');
182220
}
183221
ctx.emit('clear');
184222
if (isOpen.value) {
@@ -199,6 +237,7 @@ export default function useSelect(
199237
modelValue = checkedItems;
200238
ctx.emit('update:modelValue', modelValue);
201239
ctx.emit('remove-tag', data.value);
240+
getMultipleSelected(checkedItems);
202241
};
203242

204243
const onFocus = (e: FocusEvent) => {

packages/devui-vue/docs/components/select/index.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -469,14 +469,14 @@ export default defineComponent({
469469

470470
### Select 事件
471471

472-
| 事件名 | 类型 | 说明 | 跳转 Demo |
473-
| :------------ | :------------------------ | :--------------------------------------------------------- | :-------- |
474-
| value-change | `Function(data)` | 可选,当选中某个选项后,将会调用此函数,参数为当前选择项的值 | |
475-
| toggle-change | `Function(boolean)` | 可选,下拉打开关闭 toggle 事件 | |
476-
| focus | `Function(e: FocusEvent)` | 可选,获取焦点时触发 |
477-
| blur | `Function(e: FocusEvent)` | 可选,失去焦点时触发 |
478-
| clear | `Function()` | 可选, 通过右侧删除图标清空所有选项时触发 |
479-
| remove-tag | `Function(value)` | 可选,多选时删除单个 tag 时触发,参数为当前 tag 的值 |
472+
| 事件名 | 类型 | 说明 | 跳转 Demo |
473+
| :------------ | :------------------------ | :------------------------------------------------------------- | :-------- |
474+
| value-change | `Function(data)` | 可选,当选中值发生变化时触发,参数为目前选中的值(多选时为数组) | |
475+
| toggle-change | `Function(boolean)` | 可选,下拉打开关闭 toggle 事件 | |
476+
| focus | `Function(e: FocusEvent)` | 可选,获取焦点时触发 |
477+
| blur | `Function(e: FocusEvent)` | 可选,失去焦点时触发 |
478+
| clear | `Function()` | 可选, 通过右侧删除图标清空所有选项时触发 |
479+
| remove-tag | `Function(value)` | 可选,多选时删除单个 tag 时触发,参数为当前 tag 的值 |
480480

481481
### Select 插槽
482482

0 commit comments

Comments
 (0)