zoukankan      html  css  js  c++  java
  • react输入框输入中文bug

    一般来说,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

    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    

    然后,看一下效果

    可以看到,我们再输入中文的过程中,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

  • 相关阅读:
    基于windows server 2016和sqlserver 2016 AlwaysOn的群集配置
    Mysql基于Mysql Cluster+MysqlRouter的集群部署方案
    阿里云ECS部署Redis主备哨兵集群遇到的问题
    Informix数据库配置与连接
    Linux系统中Redis和Tomcat的PID文件路径设置
    Linux端口映射,80端口映射到8080端口
    Tomcat优化配置
    Tomcat配置自定义JAVA环境
    VMware虚拟机系统无法使用桥接联网
    PostgreSQL远程访问设置
  • 原文地址:https://www.cnblogs.com/yky-iris/p/9148151.html
Copyright © 2011-2022 走看看