Skip to content

Reactjs-Form #95

Open
Open
@yaofly2012

Description

@yaofly2012

表单(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
  1. 数据由React控制(通过上面的过程)的表单组件也叫受控组件;
    技术上来说只要指定了value属性(radio/checkbox是checked属性)的表单组件都叫"受控组件"
  2. 如果指定了value属性(radio/checkbox是checked属性),则需要同时绑定onChange事件,否则React是报Warning:
    image
  • 并且如果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:

  1. 如果表单元素很多,每个都这样做岂不是很繁琐!!!有什么好的方式吗?
  2. React在更新组件value值时如何保证光标不移动到最后?
  3. 对于没有绑定onCHange事件的且指定初始值(非undefined or null)的受控组件(input, textarea, select等),用户是无法修改值的。

三、uncontrolled组件

并不是所有的表单组件都可以作为受控组件,对于那些React不知道状态的表单组件称为"非受控组件",这其中包含:

  1. 天生就是的(即React不能控制的)
    value属性不能通过编程方式修改的表单元素,如<input type="file"/>
  2. 不采用受控组件处理流程的表单组件
    元素的表单处理方式,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

五、参考

  1. Reactjs Doc 主要概念-表单
  2. Reactjs API DOM元素
  3. React Doc 高级指引-非受控组件

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions