场景
如题,已经在此处设置了表单验证规则,并且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,这是本人目前能做到的办法了。

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

1518

被折叠的 条评论
为什么被折叠?



