跳到主要内容

compositionstart

2023年09月14日
柏拉文
越努力,越幸运

一、认识


compositionstart 文本合成系统如 input method editor(即输入法编辑器)开始新的输入合成时会触发 compositionstart 事件。例如,当用户使用拼音输入法开始输入汉字时,这个事件就会被触发。

二、语法


2.1 input

<input id="input" />

<script>
let isChinesseInput = false;
const input = document.querySelector('#input');
const isChrome = navigator.userAgent.indexOf('Chrome') > -1;

input.addEventListener('change', handleChange);
input.addEventListener('compositionend', handleCompositionend);
input.addEventListener('compositionstart', handleCompositionstart);

function handleChange(e) {
if (!isChinesseInput) {
const { value } = e.target;
console.log('value', value);
}
}

function handleCompositionend(e) {
isChinesseInput = false;
if (isChrome) {
handleChange(e);
}
}

function handleCompositionstart() {
isChinesseInput = true;
}
</script>

三、场景


3.1 input 中文输入

问题描述:

在使用 React 绑定 input 输入框的 onChange 方法时,如果使用中文输入法(或者其他输入法),会出现一个问题:还在输入拼音的时候,onChange 方法已经触发了,如下,即输入过程就已经触发了多次 onChange 方法。如果 onChange 方法有较为复杂的逻辑,就可能会带来一些用户体验或者逻辑的问题。

解决方案:

通过使用 compositionEvent 事件控制中文输入标识, 根据中文输入标识决定是否触发 onChange 。具体为: 通过监听输入法开始输入到结束的事件,即是去监听compositionstartcompositionend方法,通过设置一个变量,在两个方法里面设置 true/false,来判断是否处在中文输入拼音这个过程当中,如果是,则不触发 onChange 后续事件。

兼容处理:

  • 谷歌浏览器: compositionstart -> onChange -> compositionend, onChange 事件先于 compositionend 事件触发, 因此我们需要针对谷歌浏览器的 compositionend 结束后手动调用 onChange 处理函数。

  • 其他浏览器: compositionstart -> compositionend -> onChange

具体实现

import { useState } from 'react';
import Input, { calculateChineseLength } from './components/Input/input';

function App() {
const [value, setValue] = useState('');

const onChange = (val: string) => {
setValue(val);
console.log('中文长度为:' + calculateChineseLength(val));
};

return (
<>
<Input value={value} onChange={onChange} maxChineseLength={5} />
</>
);
}

export default App;