React中使用antd里Form组件表单验证,其中的input设置type为number,中文输入法却能却输入

本文介绍了在React应用中使用Ant Design的Form组件时,遇到input type='number'允许中文输入法输入的问题。通过分析发现中文输入法的拼音输入不会触发value变化。解决方案是利用compositionStart和compositionEnd事件,设置状态标志并使用Form的setFieldsValue()方法动态更新input值,避免异常输入。

场景

如题,已经在此处设置了表单验证规则,并且input的type为number
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

情况是,输入数字,不能输入,英文输入法下输入英文,也无法输入,

但是用中文输入法,不按回车的情况下还能输入,打完字不按回车,直接点击输入框外的区域,还能保留下输入的内容,也不触发验证,但是最后提交会触发验证
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击提交后
在这里插入图片描述

探索过程

然后给Form进行添加valuechange的监听,发现这种靠中文输入法放上去的值,并没有引起value的改变,如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
甚至,我以这个输入开头,在后面继续添加数字,依然不会有valuechange发生
在这里插入图片描述
但是如果只写数字,则会打印监听事件,如下
在这里插入图片描述
加了显示price的值的监听,也无法得到
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

网上说搜狗和微软的输入法机制不一样,链接地址
所以又试了一下,果然,微软自带的中文,就是不能输入(符合情景目的),
在这里插入图片描述
点击其他地方后,拼音就无法继续挂在上面了

在这里插入图片描述
但是,如果我这个时候截图等其他操作,然后返回去看的时候,依然可以挂在上面,但是同样不会触发value改变
在这里插入图片描述
在这里插入图片描述

解决办法

所以,问题是用中文输入法,不用回车键的输入,根本就没有输入进去,就只是把数值挂上去了,但是为什么会这样,该怎样解决呢,参考了以下文章的做法
参考1
参考2
参考3

因为中文输入法无法触发input的onchange事件,但是可以触发input的compositionStart和compositionEnd事件,在输入拼音并且尚未完成时,触发compositionStart,完成时触发end,

所以思路是,设置一个flag,在start和end之间的过程flag:true,当end触发时,flag:false,然后给input赋值,
首先想到的是设置inputRef = React.creatRef(),然后通过this.inputRef.current.state.value进行赋值,结果发现无法成功赋值,后来查明原因,是因为在antd中的Form组件里,无法通过setState进行赋值:
在这里插入图片描述
推荐使用setFieldsValue(),
所以初版代码如下:

handleComposition = evt => {
        if (evt.type === 'compositionend') {
            this.isOnComposition = false;
            this.change1()//没有给此次的change1传参,所以在拼音输入完的时候,event就会是undefined
            return;
        }
        this.isOnComposition = true;
    };

inputChange = (event) => {
        if (!this.isOnComposition) {
            if (event ===undefined) {
                // this.inputRef.current.state.value = 7,这种赋值方法无法实现目的
                this.formRef.current.setFieldsValue({
                    'price':6//先尝试赋值一个固定的,后续改进
                })
            }
        }    

render(){

  return(
	<Form
		{...layout}
		ref={this.formRef}
		onValuesChange={this.change}
	>
			<Input
				ref={this.inputRef}
				onChange={this.inputChange}//当input中value发生改变的时候,inputChange触发
				onCompositionStart={this.handleComposition}//处理flag
				onCompositionEnd={this.handleComposition}
				placeholder='请输入商品价格'
				type='number'
				addonAfter="元"
			/>
	/>	
  )
}

如此一来就可以在拼音出入后给input赋值为纯数字,而不是没有拼完的拼音,
在这里插入图片描述
但是要如何让他恢复到输入拼音之前呢,现在无论是点击中文输入法外部还是回车键结束输入,都会变成指定的数字6,
而且有两种情况,第一是一上来就输入拼音,这个时候输入框还没有数字,所以当拼音结束的时候应该赋值为空,
第二种是先输入数字,再输入拼音,拼音结束后依旧是显示之前的数字,不要拼音内容

思路是指定一个tempInput,记录有数字的情况下,暂存的值,利用onchang事件无法获得拼音,但是可以获得已经输入的数字值,给Form的onChange绑定,也可以在compositionStart的时候进行绑定,为了少一个方法,就直接在compositionStart里进行,如下:

    handleComposition = evt => {
        if (evt.type === 'compositionend') {
            this.isOnComposition = false;
            this.inputChange()
            return;
        }
        this.isOnComposition = true;
        this.tempPrice = this.inputRef.current.state.value
    };
    inputChange = (event) => {
        if (!this.isOnComposition) {
            if (event ===undefined) {
                // this.inputRef.current.state.value = 7,这种赋值方法无法实现目的
                const tempPrice = this.tempPrice || ''
                this.formRef.current.setFieldsValue({
                    'price': tempPrice
                })
            }
        }  

const tempPrice = this.tempPrice || ‘’ 因为这一句是当一开始就没有值的时候,一上来就拼音,就给一个空字符串,但是依然无法达到效果,其实这里把空字符串改成任意非空非数字的字符串即可,因为该非空字符串tempPrice会赋值给这个input,然后触发表单验证,结果发现你是字符串,所以压根就不会让你输入了,目的打成了,但是会报警告
比如我写了const tempPrice = this.tempPrice || ‘略略略’ 就会有警告如下,

在这里插入图片描述
这个原因是,相对于咱们内部给赋值上去,但是我的input设置了type=‘number’,然后发现输入的不是number,是字符串,该字符串还不能转成数字,所以就会报错,如果我注释掉type=‘number’,就不会报错,并且‘略略略’也会显示上去,
然后将inputChange函数也省略了,写到handleComposition里面,最终代码如下:

    handleComposition = evt => {
        if (evt.type === 'compositionend') {
            this.isOnComposition = false;
            const tempPrice = this.tempPrice || '略略略'
            this.formRef.current.setFieldsValue({
                'price': tempPrice
            })
            return;
        }
        this.isOnComposition = true;
        this.tempPrice = this.inputRef.current.state.value
    };

最终目的达成,但是一上来就输入拼音,虽然不会挂在上面,但是会在控制台中报警告,想了三天,截至2021.4.21,这是本人目前能做到的办法了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值