React中的受控组件与非受控组件

53 阅读3分钟

我们一般讨论到受控组件与非受控组件都是与表单有关的。

什么是受控组件

在React中,HTML表单的处理方式和普通的DOM元素不太一样:表单元素通常会保存在一些内部的state

比如下面的HTML表单元素:

  • 这个处理方式是DOM默认处理HTML表单的行为,在用户点击提交时会提交到某个服务器中,并且刷新页面(action传后端,前后端分离之前经常用,比如jsp代码)
  • 在React中,并没有禁止这个行为,它依然是有效的
  • 但是通常情况下会使用JavaScript函数来方便的处理表单提交,同时还可以访问用户填写的表单数据
  • 实现这种效果的标准方式是使用“受控组件”

image.png

  • 在 HTML 中,表单元素(如< input >、 < textarea> 和 < select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。
  • 而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
    • 我们将两者结合起来,使React的state成为“唯一数据源“
    • 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作
    • 被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”

受控组件的基本使用

代码如下:

image.png

当我们点击提交后,会自动的产生默认行为。 image.png

我们取消掉默认行为 image.png

我们监听input框 image.png image.png 我们用react的浏览器插件来看(保存是没问题的) image.png

image.png

我们还要做一个操作。让value永远和this.state.username保持一致。

image.png

当前这个组件就是个受控组件。有了受控组件我们点击提交就很方便了。

image.png

代码

import React, { PureComponent } from 'react'

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = { //每个input建议都在state里做一个保存
      username: ""
    }
  }

  render() {
    return (
      <div>
        {/* 我们把默认行为取消掉 */}
        <form onSubmit={e => this.handleSubmit(e)}>
          <label htmlFor="username">
            用户: 
            {/* 受控组件 */}
            <input type="text" 
                   id="username" 
                  //  传入事件
                   onChange={e => this.handleChange(e)}
                   value={this.state.username}
                   />
          </label>
          <input type="submit" value="提交"/>
        </form>
      </div>
    )
  }
  handleSubmit(event) { //这个event合成事件有所有的原生事件
    event.preventDefault(); //取消默认行为
  }

  handleChange(event) {
    // console.log(event.target.value);
    this.setState({
      username:event.target.value
    })
  }
}

受控组件-select的基本使用

select会稍微有一点不一样,不过大体一致。

import React, { PureComponent } from 'react'

export default class App extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      fruits: "orange" //默认值
    }
  }

  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          <select name="fruits" 
                  onChange={e => this.handleChange(e)}
                  value={this.state.fruits}>
            <option value="apple">苹果</option>
            <option value="banana">香蕉</option>
            <option value="orange">橘子</option>
          </select>
          <input type="submit" value="提交"/>
        </form>
      </div>
    )
  }

  handleSubmit(event) {
    event.preventDefault();
    console.log(this.state.fruits);
  }

  handleChange(event) {
    this.setState({
      fruits: event.target.value
    })
  }
}

受控组件多输入的情况

这个考验的还是抽离公共部分的能力。

import React, { PureComponent } from 'react'

export default class App extends PureComponent {
  constructor(props){
    super(props)

    this.state = {
      username:"",
      password:"",
      valid:""
    }
  }
  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          <label htmlFor="">
            用户:
            {/* 受控组件 */}
            <input  type="text" 
                    id='username' 
                    name = "username"
                    onChange = {e => this.handleChange(e)}
                    value = {this.state.username}
            />
          </label>
          <input type="submit"  value="提交"/>
          <br />
          <label htmlFor="">
            密码:
            {/* 受控组件 */}
            <input  type="text" 
                    id='password'
                    name = "password" 
                    onChange = {e => this.handleChange(e)}
                    value = {this.state.password}
            />
          </label>
          <input type="submit"  value="提交"/>
          <br />
          <label htmlFor="">
            验证:
            {/* 受控组件 */}
            <input  type="text" 
                    id='valid' 
                    name = "valid"
                    onChange = {e => this.handleChange(e)}
                    value = {this.state.valid}
            />
          </label>
          <input type="submit"  value="提交"/>
        </form>
      </div>
    )
  }

  handleSubmit(event){
    event.preventDefault() //取消默认事件
  }
  // handleUserChange(event){
  //   // console.log(event.target.value);
  //   this.setState({
  //     username:event.target.value
  //   })
  // }

  // handlePassChange(event){
  //   this.setState({
  //     password:event.target.value
  //   })
  // }

  // handlePassChange(event){
  //   this.setState({
  //     valid:event.target.value
  //   })
  // }
  handleChange(event){
    this.setState({
      // []:event.target.value ES6新语法:计算属性名
      [event.target.name]:event.target.value
    })
  }
}

非受控组件

在开发中不建议大家来使用。 非受控组件还是操作dom了,react中只要直接操作dom就不建议。

import React, { PureComponent, createRef } from 'react'

export default class App extends PureComponent {
  constructor(props) {
    super(props);

    this.usernameRef = createRef();
  }

  render() {
    return (
      <div>
        <form onSubmit={e => this.handleSubmit(e)}>
          <label htmlFor="username">
            用户: 
            <input type="text" id="username" ref={this.usernameRef}/>
          </label>
          <input type="submit" value="提交"/>
        </form>
      </div>
    )
  }

  handleSubmit(event) {
    event.preventDefault();
    console.log(this.usernameRef.current.value);
  }
}