你不知道的React系列(二十九)受控组件和非受控组件

125 阅读2分钟

本文正在参加「金石计划」

受控组件

  • 组件同时渲染表单和控制用户输入逻辑

  • 表单数据是由 React 组件来管理

  • state 接管表单元素(如<input><textarea><select>)的 value,setState 更新 value<input><textarea>

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = { value: "" };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleChange(event) {
        this.setState({ value: event.target.value });
      }
      handleSubmit(event) {
        alert("提交的名字: " + this.state.value);
        event.preventDefault();
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              名字:
              <input
                type="text"
                value={this.state.value}
                onChange={this.handleChange}
              />
            </label>
            <input type="submit" value="提交" />
          </form>
        );
      }
    }
    

<select> 多选

<select multiple={true} value={['B', 'C']}>
  • 处理多个输入

    • 每个元素添加 name 属性
    • 处理函数根据 event.target.name 的值选择要执行的操作
    class Reservation extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isGoing: true,
          numberOfGuests: 2,
        };
    
        this.handleInputChange = this.handleInputChange.bind(this);
      }
    
      handleInputChange(event) {
        const target = event.target;
        const value = target.type === "checkbox" ? target.checked : target.value;
        const name = target.name;
        this.setState({
          [name]: value,
        });
      }
    
      render() {
        return (
          <form>
            <label>
              参与:
              <input
                name="isGoing"
                type="checkbox"
                checked={this.state.isGoing}
                onChange={this.handleInputChange}
              />
            </label>
            <br />
            <label>
              来宾人数:
              <input
                name="numberOfGuests"
                type="number"
                value={this.state.numberOfGuests}
                onChange={this.handleInputChange}
              />
            </label>
          </form>
        );
      }
    }
    

缺点

  • 受控组件需要为数据变化的每种方式都编写事件处理函数
  • 当你将之前的代码库转换为 React 或将 React 应用程序与非 React 库集成时比较麻烦

非受控组件

  • 表单数据将交由 DOM 节点来处理

  • 不是为每个状态更新都编写数据处理函数

  • 使用 ref 来从 DOM 节点中获取表单数据

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.input = React.createRef();
      }
    
      handleSubmit(event) {
        alert("A name was submitted: " + this.input.current.value);
        event.preventDefault();
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Name:
              <input type="text" ref={this.input} />{" "}
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }
    
  • 默认值

    <input defaultValue="Bob" type="text" />
    
  • 文件输入

    始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制

    class FileInput extends React.Component {
      constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.fileInput = React.createRef();
      }
      handleSubmit(event) {
        event.preventDefault();
        alert(`Selected file - ${this.fileInput.current.files[0].name}`);
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Upload file:
              <input type="file" ref={this.fileInput} />
            </label>
            <br />
            <button type="submit">Submit</button>
          </form>
        );
      }
    }
    
    ReactDOM.render(<FileInput />, document.getElementById("root"));
    

如何选择

  • 受控组件

  • 每次改变都会调用onCahnge函数

    goshacmd.com/_next/image…

  • 数据推送给form表单

  • 输入的值改变的时候表单组件会立即响应

  • 如何选择

    特点非受控受控
    提交取值
    提交校验
    实时校验
    根据条件判断按钮状态
    强制格式化表单的值
    一条数据多个输入框
    动态输入