受控组件和非受控组件

“受控“组件和”非受控“组件通常是指的表单元素。

但是有时如果通过props将数据传入某个组件,该组件受props数据控制,也可称为“受控”组件。

如果只是受state的数据影响,则称为“非受控”组件。

 

下面介绍的主要是表单类的组件。

1. 受控组件

通过React的state作为数据唯一来源,通过变更函数调用setState方法更新数据的表单输入元素。

它们的初始值,是this.state的初始值。

1. input的type="text/number/其他输入格式"的元素,value属性,显示和控制数据; 取值e.target.value;

2. select元素也通过value控制数据,但是它的value可以通过设置multiple,传入一个数组;取值e.target.value;

3. textarea元素通过value属性显示和控制数据;取值e.target.value;

4. type="checkbox"或者"radio", 通过checked属性,显示和控制数据;取值e.target.checked;

5. 都通过onChange事件属性的处理函数及setState,来更新表单的值;

6. 如果遇到多个受控组件一起,为了合并使用处理函数,给组件添加name属性;

7. value或者checked的值如果是undefined或者null,则相当于非受控组件;

   否则,如果不使用处理函数,值无法修改。

class InputForm extends React.Component{
  constructor(props) {
    super(props);
    this.state = {
      textValue: 'initial',
      checked: false,
      radioed: false,
      areaValue: '',
      selectValue: ''
    }
  }
  handleChangeInput = (e) => {//处理函数
    const target = e.target;
    const type = target.type;
    const checkedTypes = ['radio', 'checkbox'];
    // ['radio', 'checkbox']类型的取值是e.target.value
    // 其余类型的取值是e.target.value
    let value = checkedTypes.includes(type) ? target.checked : target.value;
    console.log(value);
    const name = target.name;
    this.setState({
      [name]: value
    })
  }
  render() {
    return (
      <form>
        {/*所有的受控组件设置一个name属性,用于区分是哪个组件*/}
        <input
          name="textValue"
          type="text" 
          // 使用value传值
          value={this.state.textValue}
          onChange={this.handleChangeInput} 
        /> 
        <input
          name="checked"
          type="checkbox"
          // 使用checked传值
          checked={this.state.checked}
          onChange={this.handleChangeInput}
        />
        <input 
          name="radioed"
          type="radio"
          // 使用checked传值
          checked={this.state.radioed}
          onChange={this.handleChangeInput}
        />  
        <textarea
          name="areaValue"
          // 使用value传值
          value={this.state.areaValue}
          onChange={this.handleChangeInput}
        />  
        <select 
          name="selectValue"
          // 使用value传值
          value={this.state.selectValue}
          onChange={this.handleChangeInput}
        >
          <option value="a">A</option>
          <option value="b">B</option>
          <option value="c">C</option>
          <option value="d">D</option>
        </select>
      </form>  
    )
  }
}

2. 非受控组件

不能通过代码来控制值,只能通过用户行为操作值。通过DOM节点来处理数据。

1. type="file'的input元素是非受控组件;input的其他类型,当不使用value时,是非受控组件;

2. type="file"也可以传入multiple属性,传多个文件;

3. 组件中使用ref属性,获取DOM节点的值;

4. input[text]/select/textarea,有defaultValue属性在初次渲染时赋予初始值;

    input[checkbox][radio], 有defaultChecked属性来赋初值;

class InputForm extends React.Component{
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
    this.fileRef = React.createRef();
    this.selectRef = React.createRef();
    this.checkRef = React.createRef();
  }
  handleSubmit = (e) => {
    e.preventDefault(); //阻止表单默认提交
    const inputValue = this.inputRef.current.value;
    const selectValue = this.selectRef.current.value;
    const files = this.fileRef.current.files[0]; //单个文件
    const checkValue = this.checkRef.current.checked;
    console.log(inputValue,files,selectValue,checkValue)
  } 
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          // defaultValue初值
          defaultValue="输入"
          ref={this.inputRef}
        /> 
        <input
          type="checkbox"
          // defaultChecked初值
          defaultChecked
          ref={this.checkRef}
        /> 
        <input
          type="file"
          ref={this.fileRef}
        /> 
        <select 
          defaultValue="c" //初值
          ref={this.selectRef}
        >
          <option value="a">A</option>
          <option value="b">B</option>
          <option value="c">C</option>
          <option value="d">D</option>
        </select>
        <input type='submit'/>
      </form>  
    )
  }
}

 3. 使用场景

只能使用受控组件:

1. 即时的表单字段校验(取值范围等)

2. 强制输入格式校验

3. 按条件禁用按钮等

 

posted @ 2019-11-20 01:17  Lyra李  阅读(1289)  评论(0编辑  收藏  举报