React中文输入法与文本输入框问题

问题描述

输入中文时,每输入一个拼音都会触发onChange事件。

解决方案

compositionstart + compositionend 事件

compositionstart: 输入法编辑器开始新的输入合成时触发(如:当用户使用拼音输入法开始输入汉字时)

compositionend: 输入完成或取消时触发

1
2
3
4
5
<input
onChange={this.onChange}
onCompositionStart={this.onCompositionStart}
onCompositionEnd={this.onCompositionEnd}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
onChange = (e) => {
if (!this.composing) {
this.search(e.target.value)
}
}

onCompositionStart = () => {
// console.log("onCompositionStart")
this.composing = true
}

onCompositionEnd = (e) => {
// console.log("onCompositionEnd")
this.composing = false
this.search(e.target.value)
}

扩展:input/change/composition/keydown事件

以下内容是对公众号文章《input/change/composition/keydown事件详解》的整理补充。

input事件在因用户行为导致<input><select>,或<textarea>元素的value改变时触发。

change事件在因用户行为导致<input><select>,或<textarea>元素的value改变,并且失去焦点或回车时触发。

composition事件在输入法编辑器输入字符后触发。

keydown事件在按下键盘按键后触发。

input

MDN input

React中的onChange事件行为同原生的input事件相同。

IE9及以下浏览器不支持input事件,可以使用IE特有的propertychange事件替代。

这两个事件的区别为:

  • input事件仅在用户输入导致value属性变化时触发,通过js改变value无法触发。

  • propertychange事件当任何属性改变都会触发。

change

MDN change

change事件触发取决于表单元素的类型(type)和用户对标签的操作:

  • 对于type"radio""checkbox"input,当元素被:checked时(通过点击或者使用键盘)触发change事件

  • 当用户完成提交动作时触发,例如:

    • 点击了<select>中的一个选项

    • <input type="date">标签选择了一个日期

      • 通过<input type="file">标签上传了一个文件,等
  • 对于textareainput[type="text"],标签的值被修改并且失去焦点或回车后触发change事件

composition

包括compositionstartcompositionupdatecompositionend事件,在输入法编辑器输入过程中触发。

这三个事件分别会在输入法输入时、输入中、输入完成时触发。

例如,当用户使用拼音输入法开始输入汉字时,这个事件就会被触发。

输入数字不会触发composition,在英文输入法下输入字母也不会触发。

keydown

从按钮按下到弹起,会依次触发keydownkeypresskeyup事件。

  • keydown会在按下任意字符后触发(the keydown event is fired for all keys,经测试macOS下部分按键不会触发),keyup会在按键弹起后触发。

  • keypress会在按下可显示内容(数字/字母/符号,包括enter键)后在keydown之后触发。shift、delete等不会产生实际内容的按钮不会触发keypress。

keypress事件已经不被推荐使用,可以使用beforeinput替代。