mac和window中文输入法下,在输入框中输入英文的防抖处理的兼容
2024-12-8背景
遇到个很奇怪的问题:window 中文输入法下,在输入框(onChange做了防抖)中输入英文,会导致:每次按键后的总字符串会累加按键前的输入值。。。
先看以下demo,仅针对受控组件(非受控无本文讨论问题),代码跑起来后在中文输入法下的输入框中输入英文 d和o。
https://codesandbox.io/p/sandbox/ji-ben-shi-yong-antd-4-24-16-forked-56y8m3
import React, { useState, useCallback } from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Input } from "antd";
import { useDebounce } from "ahooks";
import { debounce } from "lodash";
const App: React.FC = () => {
const [keyword, setKeyword] = useState("");
const [keyword2, setKeyword2] = useState("");
const debouncedKeyword = useDebounce(keyword, { wait: 300 });
const onSearch = (e) => {
const value = e.target.value;
console.log(555, value);
setKeyword(value);
};
console.log(666, keyword);
console.log(777, debouncedKeyword);
// 输入很快可能掉中间的字母
const onSearch22 = useCallback(
debounce((value) => {
console.log(111, value);
setKeyword2(value);
}, 1000),
[]
);
const onSearch2 = (e) => {
console.log(7777, e.target.value);
onSearch22(e.target.value);
};
return (
<>
{/* 受控组件 */}
<Input value={keyword} onChange={onSearch} />;
{/* 输入很快可能 字母延迟显示 用户体验不好 */}
<Input value={debouncedKeyword} onChange={onSearch} />;
<Input value={keyword2} onChange={(e) => onSearch2(e)} />;
</>
);
};
export default App;
在mac电脑的chrome下,三个输入框中输入,打印结果如下
很明显没有任何问题
在window电脑的chrome下,三个输入框中输入,打印结果如下
可以看到第一张没问题。
第二张图,输入d后没有问题,当时输入o后,555和666先打印空串然后再打印 ‘ddo’。
第三张图,输入d后没有问题,当时输入o后,7777先打印空串然后再打印 ‘ddo’。
此时猜想是否与ahooks或lodash的防抖或内部定时器在window的兼容有关,于是手写防抖如下
import React, { useState, useCallback } from "react";
import "antd/dist/antd.css";
import "./index.css";
import { Input } from "antd";
function debounce(fn, wait = 50) {
let timer;
return function () {
if (!timer) {
fn.apply(this, arguments);
}
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
}
const App: React.FC = () => {
const [keyword2, setKeyword2] = useState("");
const onSearch22 = useCallback(
debounce((value) => {
console.log(111, value);
setKeyword2(value);
}, 1000),
[]
);
const onSearch2 = (e) => {
console.log(7777, e.target.value);
onSearch22(e.target.value);
};
return (
<>
<Input value={keyword2} onChange={(e) => onSearch2(e)} />;
</>
);
};
export default App;
结果和图三打印一致,猜测window和mac 在中文输入法(要弹小窗那种)在定时器加持下处理闭包的方式不同。。。于是chatGPT查询验证,果然如此!
解决办法
window中有本文问题,mac中使用:
1.尝试input方法3,如果定时时间稍长,快速输入字母,只会有最后一个字母生效。即使合理的定时时间都有可能会影响用户体验。
2.尝试input方法2,如果定时时间稍长,输入很快 字母会延迟显示,同样用户体验不好。
window中无本文问题,mac中使用:
3.尝试input方法1,展示不用防抖,防抖出来的keyword作为聚合数据排序等使用。(推荐)
有办法解决input方法3和input方法2在window中问题吗?
https://blog.csdn.net/Heartbroken_man/article/details/131199571
查询得compositionStart和compositionEnd来处理,听说vue的v-model也是这样处理.
实测:对受控Input组件无效