问题描述:
input onchange和oninput 事件输入中文时高频触发。
输入字母,数字,符号都没问题:
输入中文时问题就出来了:
每个拼音字母都触发了change,甚至输入法里的nin’hao 把拼音分开的字符也会触发。
基础代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="name">
</body>
<script>
// 1. 获取元素
var inp = document.getElementById('name');
console.log(inp);
// 2. 添加事件
inp.addEventListener('input', function () {
// 3. 获取输入的内容
var value = inp.value;
// 4. 输出内容
search(value);
});
// search 是请求接口
function search(value){
}
</script>
</html>
解决方案:
解决方案就是用 CompositionEvent 事件里的onCompositionStart 和onCompositionEnd 解决:
-
onCompositionStart 事件在用户开始使用输入法输入时触发。在这个事件中,你可以禁用或延迟处理 onChange 事件,以避免在输入过程中重复触发。
-
onCompositionUpdate 事件在用户正在使用输入法输入时触发。在这个事件中,你可以更新输入框的值,但通常不会在这个事件中执行一些重要的操作。
-
onCompositionEnd 事件在用户完成使用输入法输入时触发。在这个事件中,你可以处理最终的输入结果,更新输入框的值,并执行一些重要的操作,如发送请求、更新页面等。
这些事件主要用于处理复合字符输入,例如在中文输入法中,用户可能会输入一段拼音,然后选择对应的汉字组成词语,最后将整个词语输入到输入框中。这个过程中, onCompositionStart 会在输入开始时触发, onCompositionUpdate 会在输入过程中触发, onCompositionEnd 会在输入结束时触发。
通过使用这些事件,我们可以更好地控制输入法输入的过程,避免在输入中文拼音时多次触发 onChange 事件,并在最终输入完成时触发相应的处理逻辑。
思路:
1.定义一个全局变量 isComposing,当 onCompositionStart 正在输入时给其赋值 为true。
2.onCompositionEnd 输入结束时,给其设置成 false。
3.然后在 change和input里判断这个值,等于true时不执行搜索即可。
具体代码如下:
需要注意的是在 compositionend 事件触发时,浏览器会继续触发 input 事件,所以 search 函数会在 input 事件中被执行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="name">
</body>
<script>
var inp = document.getElementById('name');
var isComposing = false;
inp.addEventListener('compositionstart', function () {
isComposing = true;
console.log('中文开始输入');
})
inp.addEventListener('compositionend', function () {
isComposing = false;
console.log('中文结束输入');
search(inp.value);
})
inp.addEventListener('input', function () {
if (isComposing) {
return;
}
var value = inp.value;
// 执行搜索逻辑
search(value);
});
function search(value) {
console.log(value, "执行搜索");
// 实际的搜索逻辑
}
</script>
</html>
这回只执行了一次:
MDN CompositionEvent API
react 里则是使用onCompositionEnd、onCompositionStart解决。思路写法是一样的转换成react语法就行。
代码如下:
import React, { useState} from "react";
function Inp() {
//input值
const [value, setValue] = useState("");
//是否输入完成值
const [isComposing, setIsComposing] = useState(false);
const handleCompositionEnd = (e) => {
setIsComposing(false);
search();
};
const handleCompositionStart = (e) => {
setIsComposing(true);
};
const handleChange = (e) => {
let val = e.target.value;
// console.log(val);
setValue(val);
if (isComposing) return;
search();
};
const search = () => {
console.log(value,"执行搜索");
};
return (
<div className="sss">
<input
type="text"
onCompositionEnd={handleCompositionEnd}
onCompositionStart={handleCompositionStart}
onChange={handleChange}
value={value}
/>
</div>
);
}
export default Inp;