刚遇到 react input 受控组件【转载请注明来源】原创内容,盗版必究。无法输入中文的情况:
转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】ng.net转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】ng.net【未经授权禁止转载】<input value={value} onChange={onChange} />
在网上搜索了很多,知道了问题原因,但是大未经授权,禁止复制转载。【原创内容,转载请注明出处】部分文献都实际上没有解决问题。网上大部分本文作者:唐霜,转载请注明出处。【本文受版权保护】文献,只解决了 onChange 的问题【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】,但是没有解决 value 和 onCh本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。ange 一起用的问题。value 属性【本文首发于唐霜的博客】【转载请注明来源】导致 input 成为一个完完全全的受控【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】组件。value 的值决定当前 inpu【转载请注明来源】本文版权归作者所有,未经授权不得转载。t 的展示内容。因此,网上的文献只提供了本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。一些参考,并不能解决问题本质。
转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】ng.net本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】ang.net【本文受版权保护】因 value 属性导致无法输入中文的原【原创内容,转载请注明出处】【本文首发于唐霜的博客】因在于,react 会用 onChang【本文受版权保护】转载请注明出处:www.tangshuang.nete 这个接口响应任意输入,而如果在此时修本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net改 value 值,就会导致 DOM 的【未经授权禁止转载】未经授权,禁止复制转载。重绘(react 通过实时处理 inpu著作权归作者所有,禁止商业用途转载。【本文受版权保护】t 的 DOM 节点的 value 属性本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。值来保证重绘后使用正确的 value,你著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】可以通过开发者工具查看这个 input 本文作者:唐霜,转载请注明出处。【转载请注明来源】节点在输入时的变化),直接导致中文输入法本文版权归作者所有,未经授权不得转载。【本文受版权保护】框消失,输入框内变成刚才输入的英文字符(【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net甚至带空格)。onChange 接管 i【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】nput 的一系列属性,它不是单纯的 c【关注微信公众号:wwwtangshuangnet】【本文受版权保护】hange 或 input 事件。当然,【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】在 type=text 上,它主要功能是原创内容,盗版必究。原创内容,盗版必究。接管 input,但是 onInput 本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。实际上还是有效。
原创内容,盗版必究。【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】ngnet】我在 jqvm 中实际上也遇到这个问题。当时发现通过响本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net应式方法替换真实 DOM 之后,原有的输未经授权,禁止复制转载。【未经授权禁止转载】入态会消失(没有 focus),所以后来著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】解决办法是,保存原始真实 DOM,每次更转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】新后用原来的 DOM 把新绘入的 DOM【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】 给替换掉,再做一些输入态的处理(例如光【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。标位置)。
未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netng.net显然,react 的处理方式不是这样,r【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。eact 也保存了真实 DOM,但是每次【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】更新 value 之后,会对 DOM 节本文作者:唐霜,转载请注明出处。【未经授权禁止转载】点的 value 进行复杂加工。不过理论原创内容,盗版必究。本文作者:唐霜,转载请注明出处。上,react 面临同样的问题,所以它应本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】该也要解决这个输入态问题,这还会牵扯到 【版权所有,侵权必究】未经授权,禁止复制转载。focus 和 blur,下面会提到。总【作者:唐霜】【本文首发于唐霜的博客】而言之,要解决无法输入中文的问题,还是要本文作者:唐霜,转载请注明出处。原创内容,盗版必究。从真实 DOM 入手解决。
转载请注明出处:www.tangshua【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。ng.net著作权归作者所有,禁止商业用途转载。import React, { useRef } from 'react'
export function Input(props) {
const el = useRef(null)
const { onChange, onFocus, onBlur, value, defaultValue, ...attrs } = props
const _value = ('value' in props) ? value : ('defaultValue' in props) ? defaultValue : null
const handleChange = (e) => {
if (onChange) {
onChange(e)
}
}
const forceSetValue = () => {
if ('value' in props && el.current) {
const input = el.current
input.value = value
input.setAttribute('value', value)
}
}
let inputing = false
return (
<input
{...attrs}
defaultValue={_value}
ref={(input) => {
if (!input) {
return
}
el.current = input
forceSetValue()
}}
// react 在focus/blur时会重新设值,如果没有下面的操作,会导致focus/blur之后,变空
// TODO 由于是异步操作,会导致文字闪动,光标定位到最末尾
onFocus={(e) => {
setTimeout(forceSetValue, 10)
onFocus && onFocus(e)
}}
onBlur={(e) => {
setTimeout(forceSetValue, 150)
onBlur && onBlur(e)
}}
onCompositionStart={() => {
inputing = true
}}
onCompositionEnd={(e) => {
inputing = false
handleChange(e)
}}
onChange={(e) => {
if (!inputing) {
handleChange(e)
}
}}
/>
)
}
export default Input
首先第一步,就是借鉴网上资料提供的方法,转载请注明出处:www.tangshuang.net原创内容,盗版必究。干掉 value,使用 defaultV本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netalue。完成这一步之后,就可以实现正常【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。输入中文了(从这里可以看出无法输入中文的本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。罪魁祸首还是受控机制)。接下来的问题就是
【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netngnet】【访问 www.tangshuang.n原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】【版权所有,侵权必究】- 既要能够通过 onChange 把修改后【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net的值传出去, 著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net原创内容,盗版必究。et 获取更多精彩内容】转载请注明出处:www.tangshua【版权所有,侵权必究】【转载请注明来源】ng.net
- 同时又要能保证 value 属性和真实 未经授权,禁止复制转载。原创内容,盗版必究。DOM 的 value 是同步的。 【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【本文首发于唐霜的博客】ngnet】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。
这里有个问题,input 组件的 def未经授权,禁止复制转载。未经授权,禁止复制转载。aultValue 属性会带来新的问题,转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net如果由于切换视图当前组件被销毁了,再切换原创内容,盗版必究。转载请注明出处:www.tangshuang.net回来,此时由于 defaultValue【版权所有】唐霜 www.tangshuang.net【转载请注明来源】 属性的逻辑,input 的显示内容不会【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。变成新传入的 defaultValue 【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】的值,而是仍然采用之前的值。假如你一进入本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】界面的时候,defaultValue 是【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。空的(defaultValue={val未经授权,禁止复制转载。【作者:唐霜】ue} value 为空),那么当你输入转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。了一波,修改了 value,然后切走了,【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】但是你想切回来重新继续输入(defaul【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.nettValue={value} 此时 va【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】lue 不为空),你会发现 input 【原创不易,请尊重版权】【本文首发于唐霜的博客】内容空空如也。这是 defaultVal本文作者:唐霜,转载请注明出处。【未经授权禁止转载】ue 的弊端,它让 input 是非受控【本文首发于唐霜的博客】【原创内容,转载请注明出处】的。这也是为什么,我们无论用 value【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。 还是 defaultValue 都无法【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net满足我们正常输入中文的问题。
著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu原创内容,盗版必究。原创内容,盗版必究。ang.net转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。ng.net通过 onChange 把修改后的值传出【本文受版权保护】本文作者:唐霜,转载请注明出处。去这个好办。我在代码里面加了 compo【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netsitions 控制,但是实际上不需要也【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net无所谓,大不了就是 onChange 传【关注微信公众号:wwwtangshuangnet】【作者:唐霜】出去的值是不怎么好看的字符串(带空格的拼本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】音),加了 compositions 控【原创不易,请尊重版权】【原创不易,请尊重版权】制,保证每次 onChange 出去的都【原创内容,转载请注明出处】【本文首发于唐霜的博客】是完整的中文字符串,在拼音输入期间并没有未经授权,禁止复制转载。未经授权,禁止复制转载。触发 onChange,外部也不会接收到【原创内容,转载请注明出处】【原创不易,请尊重版权】。所以,本质上,无法输入中文的问题,和 本文版权归作者所有,未经授权不得转载。【本文受版权保护】compositions 无关,这个结论原创内容,盗版必究。本文作者:唐霜,转载请注明出处。可能和网上大部分资料的说法都相反。
【版权所有】唐霜 www.tangshu【转载请注明来源】【版权所有,侵权必究】ang.net【本文受版权保护】【原创不易,请尊重版权】【本文受版权保护】保证当前这个 Input 组件的 val【作者:唐霜】【关注微信公众号:wwwtangshuangnet】ue 和真实 DOM 的 value 的【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。同步,则是我这个解决办法的核心,依托真实原创内容,盗版必究。【转载请注明来源】 DOM,直接将真实 DOM 节点的 v【未经授权禁止转载】【本文受版权保护】alue 和 value attribu【作者:唐霜】原创内容,盗版必究。te 都修改为和外部传入的 value 【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。值相等,这样这个组件虽然还是 react著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net 组件,但是已经在 DOM 层面被我魔改原创内容,盗版必究。【未经授权禁止转载】了。通过这个魔改,解决了上面所说的 de著作权归作者所有,禁止商业用途转载。【转载请注明来源】faultValue 无法控制 inpu【原创不易,请尊重版权】【作者:唐霜】t 的问题。现在,在形式上,Input 转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】组件接收 value 和 onChang【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。e 两个 prop,它是一个完全支持中文本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。输入的受控组件了。
转载请注明出处:www.tangshua【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。ng.net原创内容,盗版必究。不过 react 又干了些多余的事,在每【作者:唐霜】本文版权归作者所有,未经授权不得转载。次 focus 和 blur 时,都会去【未经授权禁止转载】【原创内容,转载请注明出处】检查组件受控情况和 value 值,导致【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net非受控组件的内部状态每次都是初始值(当第【转载请注明来源】【作者:唐霜】一次进来 defaultValue 为空著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。时,那么这个 input 就一直都是空)【转载请注明来源】未经授权,禁止复制转载。。所以,我又加了 onFocus 和 o著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netnBlur 两个属性,在里面通过一个延时【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。操作,在 react 完成自己的检查之后本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】,我再去修改真实 DOM,解决这个问题。
【本文首发于唐霜的博客】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【转载请注明来源】简单总结,react 受控组件是一个大坑【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。。
【本文受版权保护】本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】

!!!太感谢了,真的好用,困扰了我一天的问题,您的讲解真的是太清楚明朗了!
发现第一次输入之后,鼠标移开的话,文字会消失,第二次移入又出现
有代码吗?给个代码看下
已经解决了,是我自己的问题
赞