共计 2447 个字符,预计需要花费 7 分钟才能阅读完成。
前言
在做搜索输入框时,产品期待实时搜索,就是边输入边搜索,然而对于中文输入法出现的效果,不同的产品可能有不同的意见,有的觉得输入未完成也应该触发搜索。但有的却认为应该在中文输入完成后再触发搜索。我发现在 vue 中通过 v -model 绑定的输入框的值,确时正常的,在中文输入未完成的时候不会修改 value 的值。针对这两种情况,分别做了屏蔽输入过程的 change 事件和 vue 中触发 change 事件。毕竟不同的需求有不同的效果,为了满足各种情况,还是都掌握的好。
如何屏蔽中文输入过程的 change 事件
在输入拼音过程也会触发 input 事件,效果如下图:
在输入中文时,拼音输入法会先显示拼音,然后在选定一个拼音后,才把真正的汉字显示在输入框里。默认情况下,输入框的 input
事件会在拼音输入时就触发,这可能会导致一些不希望的情况。
为了解决这个问题,可以使用 compositionstart
和 compositionend
事件来检测是否拼音输入中。在拼音输入中,设置一个标志(例如 isComposing
),表示正在进行拼音输入。然后,在 input
事件中,你可以检查这个标志,如果正在拼音输入,就不触发 input
事件的处理,直到拼音输入结束,你才处理最终的字符输入。
这个方法就像是在输入之前检查你是否正在输入拼音,如果是,就等拼音输入完了再处理最终的文字输入,以避免不必要的 input
事件触发。
示例
!DOCTYPE html>
html>
head>
meta charset="UTF-8">
title>中文输入法拼音输入示例/title>
/head>
body>
input type="text" id="textInput" oninput="onInput(event)" placeholder="oninput" />
script>
let isComposing = false;
const input1 = document.getElementById('textInput');
console.log("111111", input1)
input1.addEventListener('compositionstart', e=>{
console.log("监听开始");
isComposing = true;
})
input1.addEventListener('compositionend', e=>{
console.log("监听结束", );
isComposing = false;
const value = e?.target?.value;
console.log("最终的值是:", value)
})
const onInput = (e)=>{
setTimeout(()=>{
if(!isComposing)
console.log("输入完成了", e?.target?.value)
},0)
}
/script>
/body>
/html>
-
compositionstart
事件:当用户开始使用输入法输入中文拼音时,这个事件会触发。在这个事件触发时,通常会显示拼音输入的提示或候选项。 -
compositionend
事件:当用户完成拼音的选择,输入法将真正的中文字符显示在输入框中时,这个事件会触发。这表示拼音输入结束,真正的字符已经确定。
如何解决 vue 中文不触发 change 事件
然而在 vue 中却是解决过此问题的,比如我有如下代码,input 绑定 value,watch 监听 value 的变化,然后打印出 value。我这里是 vue3
template>
div>
input v-model="value" />
/div>
/template>
script setup lang="ts">
import { ref, watch } from 'vue';
const value = ref('');
watch(value, (value) => console.log('输出 value', value));
/script>
控制台输出如下:
如果你做的功能类似百度或者谷歌搜索就算是中文输入法,在输入的过程中也触发 input 事件,此时也需要去解决这个问题。
然而这个代码也就使用了 v -model,又在官网上看到,v-model 等同于:value+@input。那就试一试这个
然而将代码替换之后,效果就出来了,哈哈哈皆大欢喜,问题解决了
为什么会这样呢, 看一下源码,
Vue 3 源码仓库:https://github.com/vuejs/vue-next
分析
根据提供的 Vue 3 的 vModel
源码,确实没有处理中文输入过程中的 change
事件,这是因为 Vue 3 为了提高性能和减少不必要的事件触发,采取了一种更精细的事件处理策略。具体来说:
-
vModel
指令在created
钩子中监听了input
事件,而不是change
事件。这是因为input
事件更加实时,而change
事件通常在输入框失去焦点时触发。所以vModel
更关注实时的文本输入变化。 -
在处理
input
事件时,源码中通过检查(e.target as any).composing
来避免在中文输入法输入过程中触发事件。这是因为在中文输入法输入时,文本可能会在用户还未完成输入时进行多次变化,如果每次都触发input
事件可能导致性能问题。因此,只有当输入法输入完成时,才手动触发input
事件。
具体来说,这段代码:
addEventListener(el, lazy ? 'change' : 'input', e => {
if ((e.target as any).composing) return
})
使用 (e.target as any).composing
来判断是否正在中文输入法的“组合”过程中,如果是,就不处理事件,直到输入法输入完成。这是为了避免不必要的事件触发。
中文输入过程是否需要触发事件,这个都是看需求怎么定,不同的场景有不同的需要,所以也不能算 bug 吧,但是作为程序员,问题总该要解决的。
原文地址: input 框输入中文时,输入未完成触发事件。Vue 中文输入法不触发 input 事件?