React里受控与非受控组件

 

 

背景:

    React内部分别使用了props, state来区分组件的属性和状态。props用来定义组件外部传进来的属性, 属于那种经过外部定义之后, 组件内部就无法改变。
而state维持组件内部的状态更新和变化, 组件渲染出来后响应用户的一些操作,更新组件的一些状态。如果组件内部状态不需要更新,即没有调用过this.setState,
全部通过props来渲染也是没问题的, 不过这种情况不常见。本文所介绍的内容就是通过props和state的定义来谈谈React的受控组件和非受控组件。

 

主体:

非受控组件

顾名思义, 非受控组件即组件的状态改变不受控制.接来下我们以一个简单input组件代码来描述。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Demo1 extends Component {
    render() {
        return (
            <input />
        )
    }
}

ReactDOM.render(<Demo1/>, document.getElementById('content'))

在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,<input defaultValue={this.props.value}/>defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。
ps: 此处如果使用value代替defaultValue,会发现输入框的值无法改变。

受控组件

上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。

class Demo1 extends Component {
    constructor(props) {
        super(props);
        this.state = {
            value: props.value
        }
    }

    handleChange(e) {
        this.setState({
            value: e.target.value
        })
    }

    render() {
        return (
            <input value={this.state.value} onChange={e => this.handleChange(e)}/>
        )
    }
}

这就是最简单的受控组件模型, 我们可以通过在onChange的回调里控制input要显示的值,例如我们设置input框只能输入数字

this.setState({
    value: e.target.value.replace(/\D/g, '')
})

现在我们应该完全明白form表单中受控组件和非受控组件的关系。受控组件采取的理念类似于redux的单项数据流理念,即value值是在调用者上更新的。

 

其他参考文章:

React 表单-受控组件与非受控组件

表单是应用中不可缺少的一部分,表单不同于其他 HTML 元素,因为它要响应用户的交互,并根据用户输入显示不同的状态。React 基于propsstate的组件渲染机制,可以很好的处理表单的复杂性。在React 中,表单组件分为两种:受控组件和非受控组件。

 

  1. 受控组件
  2. 非受控组件
  3. 受控组件与非受控组件的选择

 

1. 受控组件

1.1 受React控制的值

受控组件也被称做“受限组件”或“受约束组件”。受控组件与其它React组件行为一样,其所有状态属性的更改都由React 来控制,也就是说它根据组件的propsstate来改变组件的UI表现形式。

对于一个<input>受限组件,当我们设置其value值。组件渲染后,其value值会始终保持不变:

var MyInput = React.createClass({
  render: function() {
    return <input type="text" value="itbilu.com" />;
  }
});

ReactDOM.render(
  <MyInput />,
  document.getElementById('example')
);

上面的代码渲染后是一个值为itbilu.com的 input 元素,用户在渲染后的元素里中输入任何值都不起作用,这是因为其值是受React 控制的,React已经为其赋值为itbilu.com

 

1.2 表单组件事件

React控制受控组件的值保持不变,同样其也会受组件状态的改变,其表现形式和普通React组件一样。而果想响应更新用户输入的值,可以使用React 组件事件设置状态(stateprops)。

如,我们通过组件的 onChange 事件改变input的value

var MyInput = React.createClass({
  getInitialState: function() {
    return {value: 'itbilu.com'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function() {
    return <input type="text" value={this.state.value} onChange={this.handleChange} />;
  }
});

ReactDOM.render(
  <MyInput />,
  document.getElementById('example')
);

 

1.3 受控组件的好处

受控组件的优势在于,我们可以非常容易实现对用户输入的验证,或者对用户交互做额外的处理。

如,对用户输入做截断处理:

handleChange: function(event) {
  this.setState({value: event.target.value.substr(0, 140)});
}

上面的代码会接受用户输入,并截取前 140 个字符

 

2. 非受控组件

2.1 反模式

非受控组件相对于普通React 组件或受控组件来说是一种反模式。非受控组件不受React 的状态控制(stateprops)。

如,对于<input>来说,当我们不设置其value或设置为null时就是一个非受控组件非受控的组件渲染出来的元素直接反应用户输入,其值会随用户输入的改变而改变:

var MyInput = React.createClass({
  render: function() {
    return <input type="text" />;
  }
});

ReactDOM.render(
  <MyInput />,
  document.getElementById('example')
);

非受控组件依然可以设置初始值。如,我们可以<input>defaultValue属性:

render: function() {
  return <input type="text" defaultValue="itbilu.com" />;
}

 

2.2 非受控组件的事件

和受控组件一样,非受控组件同样可以使用React 组件事件。

如,我们可监听<input>onChange事件:

var MyInput = React.createClass({
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function() {
    return <input type="text" defaultValue="itbilu.com" onChange={this.handleChange} />;
  }
});

ReactDOM.render(
  <MyInput />,
  document.getElementById('example')
);

 

2.3 非受控组件的引用

非受控组件一般没什么用途,其值并非受父组件控制,它的值受其自身控制。但是,我们可以对其添加一个ref属性,这样可以获得对非受控组件渲染后底层DOM元素的访问。

 

3. 受控组件与非受控组件的选择

React 组件应当只受状态的改变而改变,虽然使用受控组件在代码量上有所增加,但推荐使用受控组件。受控组件的组件状态由React 控制,可以更好的控制数据流,在用户输入时能够更新组件状态。

在前面的<input>示例中,一个受控组件有如下过程:

  • 通过getInitialState设置defaultValue
  • <input>渲染时设置默认值
  • onChange事件触发后,调用相关处理器
  • change事件处理更新state
  • 重新渲染<input>

 

 

 

 

 

.

posted @ 2020-02-24 15:33  剑仙6  阅读(248)  评论(0编辑  收藏  举报
欢迎访问个人网站www.qingchun.在线