react输入框输入中文bug

简介: 一般来说,react上我们都会用change事件去处理input的输入,但这样就导致一个问题,在输入中文的时候,我们还没输入完成就会触发change事件,这样显然不是理想状况。那么,怎么解决这个问题呢?首先,你需要了解3个事件,compositionstart,compositionupdate和compositionend。

一般来说,react上我们都会用change事件去处理input的输入,但这样就导致一个问题,在输入中文的时候,我们还没输入完成就会触发change事件,这样显然不是理想状况。
那么,怎么解决这个问题呢?首先,你需要了解3个事件,compositionstart,compositionupdate和compositionend。什么意思呢?

compositionstart

要开始输入中文

compositionupdate

插入新字符

compositionend

输入完成
下面是一段代码,可以copy感受一下

    class App extends React.Component {
        constructor(props) {
            super(props)
        }

    compositionstart(event) {
        console.log('开始输入', event.data);
    }

    compositionupdate(event) {
                    document.getElementById('data').innerHTML = event.data;
        console.log('正在输入的数据', event.data);
    }

    compositionend(event) {
        console.log('结束输入', event.data);
    }

    changeEvent() {
        console.log('改变');
    }

    render() {
        return (
          <div style={{padding:"50px"}}>
              <input type="text" id="test" onChange={this.changeEvent.bind(this)}
                     onCompositionStart={this.compositionstart.bind(this)}
                     onCompositionUpdate={this.compositionupdate.bind(this)}
                     onCompositionEnd={this.compositionend.bind(this)}/>
                    <span style={{marginLeft:"50px"}}>输入的数据为 <span id="data"></span></span>
          </div>
        )
    }
}
window.onload = function () {
    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    )
}

需要注意的是,要引入react和babel



然后,看一下效果
img_39e7a359e41f21fbc5e9dbb18f7df087.png

img_7e8c04af7008148817e1fdb029e90fee.png

可以看到,我们再输入中文的过程中,event.data为输入的英文值,并且连英文字符之间的分隔符也有,这样就导致一些问题,比如我们的input不允许输入特殊字符,这样我们如果用onchange去处理的话,显然不行。所以我们要想办法,在中文输入完成之后,再处理onchange事件。

明白这几个事件之后,怎么办呢?看这里

var isOnComposition = true;
class App extends React.Component {
    constructor(props) {
        super(props)
    }

    handleComposition(e) {
        console.log('type', e.type)
        if (e.type === 'compositionend') {
            // composition is end
            isOnComposition = false
        } else {
            // in composition
            isOnComposition = true
        }
    }

    changeEvent() {
        if (!isOnComposition) {
            console.log('改变');
        }
    }

    render() {
        return (
          <div>
              <input type="text" id="test" onChange={this.changeEvent.bind(this)}
                     onCompositionStart={this.handleComposition.bind(this)}
                     onCompositionUpdate={this.handleComposition.bind(this)}
                     onCompositionEnd={this.handleComposition.bind(this)}/>
          </div>
        )
    }
}
window.onload = function () {
    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    )
}

这段代码,简洁明了,我们定义一个中间变量isOncomposition,默认为true,当触发compositionend事件时,我们把它赋为false,这样change事件就会执行。在除chrome之外的其他浏览器中,compositionend事件是先于change事件触发的,所以上述代码可以很好的运行。
而在chrome浏览器中,change方法会先于compositionend事件执行,这样的话,我们的change在执行时,isOncomposition永远都是true。
怎么办呢?就是在compositionend中加一个判断!isOnComposition && isChrome,当chrome浏览器时,会在compositionend结束,执行change的方法。
代码如下

var isOnComposition = false;
const isChrome = !!window.chrome && !!window.chrome.webstore
class App extends React.Component {
    constructor(props) {
        super(props)
    }

    handleComposition(e) {
        console.log('type', e.type)
        if (e.type === 'compositionend') {
            // composition is end
            isOnComposition = false

            if (!isOnComposition && isChrome) {
                // fire onChange
                this.changeEvent(e);
            }
        } else {
            // in composition
            isOnComposition = true
        }
    }

    changeEvent() {
        if (!isOnComposition) {
            console.log('改变');
        }
    }

    render() {
        return (
          <div>
              <input type="text" id="test" onChange={this.changeEvent.bind(this)}
                     onCompositionStart={this.handleComposition.bind(this)}
                     onCompositionUpdate={this.handleComposition.bind(this)}
                     onCompositionEnd={this.handleComposition.bind(this)}/>
          </div>
        )
    }
}
window.onload = function () {
    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    )
}

github地址如下,欢迎大家查看

react-input

相关文章
|
2月前
|
JavaScript 前端开发
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
80 1
|
3月前
|
存储 前端开发
react如何拿输入框的值
react如何拿输入框的值
47 3
|
4月前
|
前端开发 JavaScript
在React中,如何通过事件处理函数来管理输入框的获取和失去焦点行为?
【5月更文挑战第28天】在React中,如何通过事件处理函数来管理输入框的获取和失去焦点行为?
164 1
|
12月前
|
前端开发
react 获取表单中输入框的值
react 获取表单中输入框的值
113 0
|
前端开发 JavaScript
我发现了一个React、Vue等所有前端框架都存在的隐秘Bug?
我发现了一个React、Vue等所有前端框架都存在的隐秘Bug?
|
前端开发 Go
React 路由的使用以及bug规避:路由跳转、路由传参、嵌套路由
React 路由的使用以及bug规避:路由跳转、路由传参、嵌套路由
195 0
|
前端开发
react项目实战学习笔记-学习20-修改下拉菜单的小bug
react项目实战学习笔记-学习20-修改下拉菜单的小bug
190 0
react项目实战学习笔记-学习20-修改下拉菜单的小bug
|
前端开发 JavaScript 容器
react-async/await -antd-InputItem 输入框用法
1.antd-mobile 2.这里使用antd的移动端框架antd-mobile来分析下 react中的输入框具体用法
389 0
|
1月前
|
前端开发 JavaScript UED
React 基础与实践 | 青训营笔记
React 基础与实践 | 青训营笔记
40 0
|
2月前
|
前端开发 JavaScript Java
React 速通笔记
【7月更文挑战第17天】
35 1