- ...
- <input ref="inputTest" type="text" placeholder="测试" value={this.state.val}
- onChange={this.inputValue}/>
- ...
- inputValue(e){
- this.setState({
- val:e.target.value
- })
- }
以上这段代码,相信大家再熟悉不过了,react controlled 组件的最简单的栗子,controlled input 组件。首先我们来说一说 React 的事件,包括上面我们使用的 onChange 事件,都属于 React 的合成事件,也就是非浏览器原生的,它是对浏览器原生事件的封装事件。react 合成事件中,onChange 事件类似于原生的 input 事件,只要按键就会触发,这在 pc 上面或者英文输入法中不会有任何问题,但是对于移动端输入时需要切换中文输入法或者其他不同输入法的其他语言的用户来说,会粗大事。比如上面这段最简单的代码,我们想要输入中文,比如 "事件",我们需要在手机键盘按键'shijian', 每按一次键都会触发 onChange 事件,然后会发现输入框的内容已经输入了英文字母,这不是我们需要的结果。那怎么解决呢?接下来,我们的主角出场 --compositionEvent。组合事件可以帮助我们解决这个问题,可以参看 组合事件参考文档 。
我们还是以输入中文为例,大家会发现,在移动设备中,中文的输入其实分为三个步骤(pc 上其实也是一样),1: 开始,2: 敲键盘,3: 点击选择中文。这个 compositionEvent 组合事件就是分拆了不同的步骤的事件的组合,这个组合事件是由 compositionStart,compositionUpdate 和 compositionEnd 三个事件的组合,Start 和 End 事件只执行一次,Update 会执行多次,只要没有选中中文之前,触发 update 事件,选中需要的选中的文字,就会触发 end 事件,一个组合事件完成,以此循环。了解了组合事件这个原理后,解决方案就不难理解了吧。
使用这种方式就基本上与 pc 浏览器的效果就一致了,请看如下代码,只添加了组合事件中 End 的监听,意味着若我们完成输入最后一步选中操作后,才会触发该监听。大家肯定会疑问,这不就是的 onInput 效果吗,那不就能够支持到 controlled 组件的方式,对不起,真不行,因为输入确实完美契合,但是删除操作,就无法触发这个监听了。所以,如果不加上 onChange 事件的配合,那就使用 uncontrolled 组件的方式吧。
- <input ref="inputTest" type="text" placeholder="测试" onCompositionEnd={this.handleComposition}
- />
上面已经提到 controlled 组件的解决方式了,那就是与 onChange 事件进行配合,那具体如何配合呢,请看代码如下:
- <input ref="inputTest" type="text" placeholder="测试"
- onCompositionStart={this.handlingComposition}
- onCompositionUpdate={this.handlingComposition}
- onCompositionEnd={this.handleComposition}
- onChange={this.inputValue}/>
- ...
- handlingComposition(){
- this.isCompositionEnd = false;
- }
- handleComposition(e){
- this.isCompositionEnd = true;
- }
- inputValue(e){
- if(this.isCompositionEnd){
- this.setState({
- val:e.target.value
- })
- }
- }
以上代码会存在一点小问题,需要确保 onCompositionEnd 在 onChange 事件前触发,一旦有的浏览器存在兼容问题,两者的执行顺序相反,会导致 onChange 事件永不触发,因此,最好在 handleComposition 函数中重复执行一次 onChange 中的逻辑,避免出现兼容问题。 前端发展日新月异,交流也是很好的学习方式,有不对的地方,请喷!
来源: https://juejin.im/post/5a3cccdb6fb9a04500034053