使用input事件监听输入框变化时,如果当前使用的输入法是中文,他也会触发input事件,正常来说,中文没有输入完毕是不用触发事件的。
控制台打印时发现:
那么我们应该怎么去规避这件事呢?
其实input还有几个事件:
- compositionstart:事件在用户开始使用输入法输入时触发。
- onCompositionUpdate:事件在用户正在使用输入法输入时触发
- compositionend: 事件在用户完成使用输入法输入时触发
我们可以建立一个全局变量
const isComposing = ref(false);
在handleCompositionStart和handleCompositionEnd的事件中更改这个全局变量
const handleCompositionStart = () => {
isComposing.value = true;
};
const handleCompositionEnd = (event: Event) => {
isComposing.value = false;
};
在input事件中判断是否是中文输入法输入中的状态
const input = (event: Event) => {
if (isComposing.value) {
return;
}
const value = (event.target as HTMLInputElement).value;
emit("update:modelValue", value);
emit("change", value); // 添加此行代码
};
最后在handleCompositionEnd事件中添加如下代码:
const handleCompositionEnd = (event: Event) => {
isComposing.value = false;
const value = (event.target as HTMLInputElement).value;
emit("update:modelValue", value);
emit("change", value);
};
最后即可解决这个问题!
最后附上我封装的input组件(若觉得组件功能不完善,可以自行扩展组件)
MyInput.vue
<template>
<div class="input-wrapper" :class="{ 'is-focused': isFocused }">
<span class="prefix">
<slot name="prefix"></slot>
</span>
<input
:type="type"
@input="input"
:placeholder="placeholder"
:disabled="disabled"
:readonly="readonly"
:maxlength="maxlength"
@focus="handleFocus"
@blur="handleBlur"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
/>
<span class="suffix">
<slot name="suffix"></slot>
</span>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const isFocused = ref(false);
const isComposing = ref(false);
const props = defineProps<{
type?: string;
modelValue: string;
placeholder?: string;
disabled?: boolean;
readonly?: boolean;
maxlength?: number;
}>();
const handleFocus = () => {
isFocused.value = true;
};
const handleBlur = () => {
isFocused.value = false;
};
const emit = defineEmits<{
(e: "update:modelValue", value: string): void;
(e: "change", value: string): void;
}>();
// 监听是否是中文输入事件
const handleCompositionStart = () => {
isComposing.value = true;
};
const handleCompositionEnd = (event: Event) => {
isComposing.value = false;
const value = (event.target as HTMLInputElement).value;
emit("update:modelValue", value);
emit("change", value);
};
const input = (event: Event) => {
if (isComposing.value) {
return;
}
const value = (event.target as HTMLInputElement).value;
emit("update:modelValue", value);
emit("change", value);
};
</script>
<style scoped>
.input-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 1px 11px;
border-radius: 10px;
box-shadow: 0 0 0 1px #b5b5b5 inset;
}
.input-wrapper.is-focused {
box-shadow: 0 0 0 2px #2478f2 inset;
}
input {
width: 100%;
flex-grow: 1;
padding: 0;
outline: 0;
border: none;
background: 0 0;
box-sizing: border-box;
outline: 0;
font-size: 14px;
line-height: 30px;
}
input:disabled {
background-color: #000000;
cursor: not-allowed;
}
input[readonly] {
background-color: #000000;
cursor: default;
}
.prefix {
margin-right: 8px;
}
.suffix {
margin-left: 8px;
}
</style>