【SORT PLAN 4】受控组件和非受控组件

1,049 阅读4分钟

受控组件和非受控组件

一、项目情景

在项目中使用到Antd的Form组件时,会遇到需要嵌套Select组件的情况(可能会嵌套其他组件),这时候,当使用Select自身设置value的方式去修改值,是不生效的。

<Form>
  <Form.Item name=”itemName“>
    <Select>
      <Option value="jing"></option>
    </Select>
  </Form.Item>
</Form>
  • Form.getFieldsValue()
  • Form.getFieldValue(name)
  • form.setFieldsValue({ [itemName]: value });
// 查询当前item的列中的字段
    item.columns?.forEach((i: any) => {
       if ('' + i.id === value) {
         form.setFieldsValue({
           [itemName]: value
        });
     }
  });

二、知识点

2.1 受控组件

在HTML中,标签<input>、<textarea>、<select>的值的改变通常是根据用户输入进行更新。在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。

受控组件就是为某个form表单组件添加value属性

return <input type="text" value="Hello!" />;

添加了value 属性的表单组件元素其内部是不会维护自己状态state,组件的value值一旦设置某个具体值就始终是这个值,所以需要调用者来控制组件value的改变。

2.2 非受控组件

表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用 ref从DOM获取表单值)

非受控组件就是没有添加value属性的组件

 <input type="text" />

非受控组件在底层实现时是在其内部维护了自己的状态state;这样表现出用户输入任何值都能反应到元素上。

三、理解

受控组件和非受控组件是react处理表单的入口,数据控制一切或者页面生成与更新依赖于执行jsx的指令。

单表单元素有特别的地方,用户可以通过键盘与鼠标选择,改变界面的显示,界面的改变也意味着有一些数据被改动,比较明显的input的value,textarea的innerHTML,radio/checkbox的checked,option的selected与selectedInedx,这两个被动修改的

<input value = {this.state.value} />

当input.value是由组件的state.value出来的,当用户进行输入修改后,然后重新刷新试图,这时,input.value是采取用户的新值还是state的新值呢?

react认为value/checked不能单独存在,需要与onInput/onChange/disabed/readOnly等控制value/checked的属性或事件一起使用。 它们共同构成受控组件

如果用户没有写这些额外的属性与事件,那么框架内部会给它添加一些事件,如onClick, onInput, onChange,阻止你进行输入或选择,让你无法修改它的值。在框架内部,有一个顽固的变量,我称之为 persistValue,它一直保持JSX上次赋给它的值,只能让内部事件修改它。

  • 受控组件是可通过事件完成的对value的控制。

  • 在受控组件中,persistValue总能被刷新。

再看非受控组件,既然value/checked已经被占用了,React启用了HTML中另一组被忽略的属性defaultValue/defaultChecked。一般认为它们是与value/checked相通的,即,value不存在的情况下,defaultValue的值就当作是value。

表单元素的显示情况是由内部的 persistValue 控制的,因此defaultXXX也会同步persistValue,然后再由persistValue同步DOM。但非受控组件的出发点是忠实于用户操作,如果用户在代码中

input.value = "xxxx"
<input defaultValue={value} /> // 就再不生效,一直是xxxx

四、总结

  • 受控元素,一般用在需要动态设置其初始值的情况;例如某些form表单信息编辑时,input表单元素需要初始显示服务器返回的某个值然后进行编辑。
  • 非受控元素, 一般用于无任何动态初始值信息的情况; 例如form表单创建信息时,input表单元素都没有初始值,需要用户输入的情况

受控组件就是可以通过react的state,onChange改变值(<input>、<textarea>、<select>),但是非受控组件是自己维护自身状态,向form表单

在Antd的tree组件里,当给其只设置了默认属性,此时tree为非受控组件;

当给其设置了不带有default的属性(受控属性),此时tree为受控组件;

因此可以看出:属性名称中不带有default的为受控属性,带有default的为非受控属性;