Description
表单(Form)
相对于只展示内容的元素,表单元素比较特殊些,他们有自己的内部状态(value值),并且用户的交互可以修改这些内部状态。
站在React角度看任何UI的数据必须来自组件的state。所以对于表单组件React也尽量保证state是“唯一数据源”
一、React尽量磨平各表单元素的行为差异
1.1 统一使用value表示元素的值
input, textarea, select统一使用value属性指定值
1.2 值变化统一onChange
事件
和DOM的onChange
触发方式是不同的。
- DOM元素触发时机:blur + 值变化;
- React元素触发时机:值变化。
二、受控组件
保证React state作为唯一数据源(single source of truth)。
如何保证表单内部状态和React组件状态一致?
- 使用定义的组件state属性渲染表单组件;
- 监听表单值发生变化事件,在事件处理函数里更新组件state。
React会重新渲染组件
Element | Value property | Change callback | New value in the callback |
---|---|---|---|
<input type="text" /> | value="string" | onChange | event.target.value |
<input type="checkbox" /> | checked={boolean} | onChange | event.target.checked |
<input type="radio" /> | checked={boolean} | onChange | event.target.checked |
<textarea /> | value="string" | onChange | event.target.value |
<select /> | value="option value" | onChange | event.target.value |
- 数据由React控制(通过上面的过程)的表单组件也叫受控组件;
技术上来说只要指定了value
属性(radio/checkbox是checked属性)的表单组件都叫"受控组件" - 如果指定了
value
属性(radio/checkbox是checked属性),则需要同时绑定onChange
事件,否则React是报Warning:
- 并且如果
value
指定的值不是null
或则undefined
, 则此时用户是无法输入内容的!为什么呢?
因为对于受控表单组件,React为了保证唯一数据源,它在渲染DOM时是采用组件value
属性值作为表单的值,用户是无法直接修改表单值的。
In the React rendering lifecycle, the value attribute on form elements will override the value in the DOM
- 为啥
value
指定的值是null
或则undefined
又可以编辑?
估计此时React当做非受控组件处理了,得看代码了。
2.2 默认值
2.2.1 统一方式
input, textarea, select统一使用value属性指定值,那默认值也也就是对应state的默认值即可。
2.2.2 特殊的select
组件
option的selected
属性也可以指定select
组件的展示值,但是这不表示select
组件的state值。
2.3 Issues/Concern:
- 如果表单元素很多,每个都这样做岂不是很繁琐!!!有什么好的方式吗?
- React在更新组件value值时如何保证光标不移动到最后?
- 对于没有绑定onCHange事件的且指定初始值(非undefined or null)的受控组件(input, textarea, select等),用户是无法修改值的。
三、uncontrolled组件
并不是所有的表单组件都可以作为受控组件,对于那些React不知道状态的表单组件称为"非受控组件",这其中包含:
- 天生就是的(即React不能控制的)
value属性不能通过编程方式修改的表单元素,如<input type="file"/>
- 不采用受控组件处理流程的表单组件
元素的表单处理方式,React无法知道DOM元素的值
3.1 唯一数据源
对于非受控组件唯一数据源来自DOM元素(即来自用户的交互),获取值可利用ref
。
3.2 初始值
使用defaultValue
属性(radio/checkbox是defaultChecked属性)。不能使用value
属性(radio/checkbox是checked属性),这个是用于受控组件的。如果使用value
属性(radio/checkbox是checked属性)初始化表单值,会命中受控组件的部分规则,导致用户无法修改值。
3.3. 关于非受控组件的描述
- React建议尽量使用受控组件,除非要结合非react技术的代码或者使用天生就是非受控的组件。
- 非受控组件有时候可能编码比较快,但是比较脏。
quick and dirty
四、到底选择哪种表单处理方式呢?
Controlled and uncontrolled form inputs in React don't have to be complicated