React学习手记4-组件分类(受控组件和非受控组件)

825 阅读3分钟

组件可以按不同角度做分类,这次从表单元素的使用开始。不同于div、span等元素只需根据状态来展示内容,表单元素自身可以维护一些状态,但是默认不受React控制。比如,一个input输入框,会随用户的输入而改变。这样的交互行为明显违背了React的基本原则--状态的改变必须通过组件的state。

受控组件

为了达到由React来控制表单元素的值,可以在用户和表单元素发生交互时控制表单元素的行为,从而保证组件的state成为表单元素状态的唯一来源,也就是表单元素的值是由React来管理。

不同表单元素实现的方式不一样

文本框

文本框包含类型为text的<input>元素和<textarea>元素。通过表单元素的value属性设置表单元素的值,通过onChange事件监听值得变化,并将变化同步到React组件的state中

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: ''};
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    const target = event.target;
    this.setState({[target.name]: target.value});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input name="name" type="text" value={this.state.name}  onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

下拉列表

<select name="cars">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
    <option value="fiat" selected="selected">Fiat</option>
</select>

React与原生使用selcted定义选中项不同,它通过在<selcet>上定义value属性来决定那个<option>元素处于选中项。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({value: event.target.value});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
            <select name="cars" value={this.state.value} onChange={this.handleChange}>
                <option value="volvo">苹果</option>
                <option value="saab">香蕉</option>
                <option value="fiat">凤梨</option>          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

复选框和单选框

类型为checkbox和radio的<input>元素,受控方式不同于text类型。React控制的不在是value属性,而是checked属性。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
        apple: false,
        orange: false
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    const target = event.target;
    this.setState({[target.name]: target.checked});
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Apple
          <input name="apple" type="checkbox" vlaue="apple" checked={this.state.apple}  onChange={this.handleChange} />
        </label>
        <label>
          orange
          <input name="apple" type="checkbox" vlaue="orange" checked={this.state.orange}  onChange={this.handleChange} />      </label>

        <input type="submit" value="Submit" />      </form>
    );
  }
}

非受控组件

受控组件需要每个元素绑定onChange事件,比较繁琐。另一种方式就是使用非受控组件,不用React来管理状态,所以需要一种方式来获取到表单元素的值。

ref

React提供了一个特殊的属性ref,用来引用React组件或DOM元素的实例,故可以通过为表单元素定义ref属性来获取元素的值。

handleSubmit(event){
    // 通过this.input 获取到input元素的值
    alert(“value is" + this.input.vlaue);
    event.preventDefault()
}

//this.input 指向当前input元素
<input type="text" ref={(inptu) => this.input = input} />

ref值是个函数,会接受当前元素作为参数,然后把input赋值给了this.input。进而可以在组件的其他地方通过this.input获取这个元素。

defaultValue

因为使用非受控组件,通常需要设置默认值,但是无法再通过value属性设置。所以可以使用defaultValue属性设置默认值。类似的,select和textarea也可以设置defalutValue,<input type="checkbox"> 和<input type="radio">则设置defaultChecked属性设置默认值。