• 受控组件和非受控组件


    React的受控组件与非受控组件的概念是相对于表单而言的,在React中表单元素通常会持有一下内部的state,因此它的工作方式与其他HTML元素不一样,而获取表单元素内部state的实现方式的不同,就产生了受控组件和非受控组件。

    受控组件

    HTML的表单元素中,它们通常自己维护一套state,并随着用户的输入自己进行UI上的更新,这种行为是不被我们程序所管控的,而如果将React里的state属性和表单元素的值建立依赖关系,再通过onChange事件与setState()结合更新state属性,就能达到控制用户输入过程中表单发生的操作,React以这种方式控制取值的表单输入元素就叫做受控组件。
    React中定义了一个input输入框的话,它并没有类似于Vuev-model的这种双向绑定功能,也就是说我们并没有一个指令能够将数据和输入框结合起来,用户在输入框中输入内容,然后数据同步更新。

    1. class Input extends React.Component {
    2. render () {
    3. return "username" />
    4. }
    5. }

    用户在界面上的输入框输入内容时,它是自己维护了一个state,这个state并不是我们平常看见的this.state,而是每个表单元素上抽象的state,这样的话就能根据用户的输入自己进行UI上的更新,如果我们想要控制输入框的内容,而输入框的内容取决的是input中的value属性,那么我们可以在this.state中定义一个名为username的属性,并将input上的value指定为这个属性。

    1. class Input extends React.Component {
    2. constructor (props) {
    3. super(props);
    4. this.state = { username: "1" };
    5. }
    6. render () {
    7. return "username" value={this.state.username} />
    8. }
    9. }

    但是这时候你会发现input的内容是只读的,因为value会被我们的this.state.username所控制,当用户输入新的内容时,this.state.username并不会自动更新,这样的话input内的内容也就不会变了,此时控制台通常会抛出一个Warning

    Warning: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.

    您为表单字段提供了一个没有onChange处理程序的value属性,这将呈现只读字段,如果字段应该是可变的,请使用defaultValue,否则请设置onChangereadOnly
    这段Warning其实给出了对于这个问题的解决方案,我们只需要对组件的onChange事件来监听输入内容的改变并使用setState更新this.state.username即可,如此我们在当前组件中能够控制这个表单元素的值,这就是受控组件。

    1. class Input extends React.Component {
    2. constructor (props) {
    3. super(props);
    4. this.state = { username: "1" };
    5. }
    6. render () {
    7. return (
    8. <>
    9. "username" value={this.state.username}
    10. onChange={e => this.setState({username: e.target.value})}
    11. />
    12. )
    13. }
    14. }

    此外需要注意的是,如果是讲此组件作为一个共用的组件用以调用的话,是有弊端的,尽管此时Input组件本身是一个受控组件,但与之相对的调用方失去了更改Input组件值的控制权,所以对调用方而言,Input组件是一个非受控组件,以非受控组件的使用方式去调用受控组件是一种反模式,下边的例子都是属于Hooks的写法。

    1. // 组件提供方
    2. function Input({ defaultValue }) {
    3. const [value, setValue] = React.useState(defaultValue)
    4. return setValue(e.target.value)} />
    5. }
    6. // 调用方
    7. function UseInput() {
    8. return
    9. }

    如果要对于组件提供方还是调用方Input组件都为受控组件,只需要提供方让出控制权即可。

    1. // 组件提供方
    2. function Input({ value, onChange }) {
    3. return
    4. }
    5. // 调用方
    6. function UseInput() {
    7. const [value, setValue] = React.useState(1);
    8. return setValue(e.target.value)} />
    9. }

    非受控组件

    如果表单元素并不经过state,而是通过ref修改或者直接操作DOM,那么它的数据无法通过state控制,这就是非受控组件。

    1. class Input extends React.Component {
    2. constructor (props) {
    3. super(props);
    4. this.input = React.createRef();
    5. }
    6. render () {
    7. return (
    8. <>
    9. "username" ref={this.input} />
    10. )
    11. }
    12. }

    总结

    受控组件

    • 每当表单的状态发生变化时,都会被写入到组件的state中。
    • 在受控组件中,组件渲染出的状态与它的valuechecked prop相对应。
    • react受控组件更新state的流程:
      • 通过在初始state中设置表单的默认值。
      • 每当表单的值发生变化时,调用onChange事件处理器。
      • 事件处理器通过合成对象event拿到改变后的状态,并更新应用的state
      • SetState触发视图的重新渲染,完成表单组件值的更新。

    非受控组件

    • 如果一个表单组件没有value prop就可以称为非受控组件。
    • 非受控组件是一种反模式,它的值不受组件自身的stateprops控制。
    • 通常需要为其添加ref prop来访问渲染后的底层DOM元素。
    • 可通过添加defaultValue指定value值。
  • 相关阅读:
    【React】史上最简单的 减少重复渲染 思路,原来这么简单?
    Python学习笔记--类的多态
    【QT开发(1)】基于c++17的代码项目模板:QT build with Cmake
    分享5款.NET开源免费的Redis客户端组件库
    Python---正则表达式
    Feign源码解析:初始化过程(一)
    np中的normalize/histogram/cumsum/interp函数
    Redis 内存淘汰和过期删除策略
    《最新出炉》系列初窥篇-Python+Playwright自动化测试-16-处理模态对话框弹窗
    人大女王金融硕士项目——比努力更重要的,是要学会做对的选择
  • 原文地址:https://blog.csdn.net/weixin_41829196/article/details/126596307