输入框里面的值通过正则匹配改变导致的光标问题(坑!!)

前言

需求是这样的,输入加油卡号,每隔输入4位自动加上一个横杠,如图:


这个光标问题是个坑,,加班到10点还没解决好。。。

解决方法

首先,这里我使用的方法是监听输入,使用正则匹配。

 <p className="addcard_tip">卡号:</p>
 <input type="tel" id="cardNum" value={this.state.cardid} className="input_info" onClick={() => { this.inputClick() }} onChange={(e) => { this.inputCardid(e) }} style={{ "left": "66px" }} maxLength={this.state.type ? CARDID_LEN_SHIYOU+3 : CARDID_LEN_SHIHUA+4} placeholder={`请输入${this.state.type ? CARDID_LEN_SHIYOU : CARDID_LEN_SHIHUA}位卡号`} />
inputCardid(e) {
        var input = document.getElementById('cardNum'), deforeValue = '';
        let cardid = input.value.replace(/\-/g, '').replace(/(.{4})(?=.)/g, '$1-'); //把input输入框的值,通过正则每隔4位插入横杠'-'
        if (e) {
            var start = this.getSelectionStart(input);  //获取现在光标的位置
           
            this.setState({
                cardid: input.value.replace(/\-/g, '').replace(/(.{4})(?=.)/g, '$1-') //把通过正则匹配后的值设置为input的value,同时也和state做一个双向绑定
            },()=>{
              
                    this.setSelectionStart(input, start);//setState完了以后,再重新设置实际上的光标
           
            }
        } else {
            cardid = this.state.cardid;
        }
      
    }
getSelectionStart(input) {
        var realStart = input.value.substring(0, input.selectionStart || 0).replace(/\-/g, '').length;
        return realStart + (parseInt((realStart - 1) / 4));//这里,获取的是实际上正则匹配后光标的位置
    }
    setSelectionStart(input,start) {
        input.setSelectionRange(start, start)
    }
    inputClick(){
        var input = document.getElementById('cardNum');
        var start = this.getSelectionStart(input);
        this.setSelectionStart(input,start);
    }

这里,在ios上是完美表现的,然而在安卓上就会光标出现问题,就是我输入了第五位,在第五位前面通过js改变了input的值,但是,我的光标还是停留在'-'的后面,不是预期的在输入的值的最后。

然后,我就开始了一个疯狂的踩坑模式,陷入一个死循环...把光标强制在最后一位,但是这样无法修改中间的值..

后来,开始怀疑是不是设置光标的时机不对,但是已经设置在setState完成的回调里面了。

后来,尝试给设置光标的方法再加一点延迟。

inputCardid(e) {
        var input = document.getElementById('cardNum'), deforeValue = '';
        let cardid = input.value.replace(/\-/g, '').replace(/(.{4})(?=.)/g, '$1-'); //把input输入框的值,通过正则每隔4位插入横杠'-'
        if (e) {
            var start = this.getSelectionStart(input);  //获取现在光标的位置
           
            this.setState({
                cardid: input.value.replace(/\-/g, '').replace(/(.{4})(?=.)/g, '$1-') //把通过正则匹配后的值设置为input的value,同时也和state做一个双向绑定
            },()=>{
              
                     setTimeout(() => {
                    this.setSelectionStart(input, start);
                }, 30);//setState完了以后,再重新设置实际上的光标
           
            }
        } else {
            cardid = this.state.cardid;
        }
      
    }

然后,就解决了。。

这里, 在setState完成后进行光标重置,但是还没有把input里面的value写入,因此再加一点点延迟,就可以重置光标了。


猜你喜欢

转载自blog.csdn.net/chiuwingyan/article/details/80655171