表单

诸如<input><textarea><option>的表单组件与其它原生(native)组件不同,因为它们可以通过用户交互而被改变。这些组件提供的接口使得管理表单对用户交互的响应更加容易。

传统表单事件

传统表单的提交

<form action='https://www.baidu.com' method='GET'>
//action表单提交的地址
//method表单提交的方式(GET比较小的数据提交,POST比较保密的提交)
    <input type="text" name="hello" placeholder="输入内容">
    <button>提交</button>
    //button作为提交按钮使用
</form>

表单的事件

  • onSubimit(表单提交)
  • onChange(域的内容改变)
  • onInput(输入框内容的改变)
  • onBlur(失去焦点)//焦点事件
  • onFocus(获得焦点)//焦点事件

inputtype属性

描述
button定义可点击按钮(多数情况下,用于通过 JavaScript 启动脚本)
checkbox定义复选框
file定义输入字段和 "浏览"按钮,供文件上传
hidden定义隐藏的输入字段
image定义图像形式的提交按钮
password定义密码字段。该字段中的字符被掩码
radio定义单选按钮
reset定义重置按钮。重置按钮会清除表单中的所有数据
submit定义提交按钮。提交按钮会把表单数据发送到服务器
text定义单行的输入字段,用户可在其中输入文本。默认宽度为 20 个字符
email定义邮箱

表单重置

import React from 'react'

class App extends React.Component {
  handleSubmit(e){
    e.preventDefault()
    //preventDefault 阻止跳转方法
    document.getElementById('form').reset()
  }
  render() {
    return (
      <div className="app">
        <form action='https://www.baidu.com' method='GET' id='form' onSubmit={this.handleSubmit.bind(this)}>
          <input type="text" name="hello" placeholder="输入内容" />
          <button>提交</button>
          <button type='reset'>重置</button>
          //重置按钮
        </form>
      </div>
    )
  }
}
export default App

小贴士reset()方法可把表单中的元素重置为它们的默认值

受控组件

非受控组件

import React from 'react'

class App extends React.Component {
  render() {
    return (
      <div className="app">
          <input type="text" placeholder="输入内容" value='123' />
        </form>
      </div>
    )
  }
}
export default App

一个没有value属性的<input>就是一个非受控组件。通过渲染的元素,任意的用户输入都会被立即反映出来。非受控的<input>只能通过OnChange函数来向上层通知自己被用户输入的更改。

可以用ref来拿到 输入的 value 值

<input ref={value => this.username = value} />
//this.username.value 拿到输入的值

注意:使用value代替defaultValue,会发现输入框的值无法改变

受控组件

表单的value值收到state的控制

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.handleChange = this.handleChange.bind(this)
    this.state = {
      input:''
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let {input} = this.state
  }
  handleChange(e){
    this.setState({
      input:e.target.value
      //触发事件目标对象的value
    })
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
          <input value={this.state.input} onChange={this.handleChange} />
          <button>提交</button>
        </form>
      </div>
    )
  }
}
export default App

表单的selecttextarea输入

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.state = {
      textarea:'',
      fruits:'banana'
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let {textarea,fruits} = this.state
    console.log(textarea,fruits)
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
          <textarea cols="30" rows="10" value={this.state.textarea} onChange={e => this.setState({textarea:e.target.value})}></textarea><br/>
          <select value={this.state.fruits} onChange={e => this.setState({fruits:e.target.value})}>
            <option value="apple">苹果</option>
            <option value="orange">橘子</option>
            <option value="banana">香蕉</option>
            //默认值通过state控制,使用selected会被警告
          </select><br/>
          <button type='submit'>提交</button>
        </form>
      </div>
    )
  }
}
export default App

表单的radio输入

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.state = {
            sex:'male'
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let obj = this.state
    console.log(obj)
  }
  handleChange(e){
    this.setState({
      input:e.target.value
    })
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
                    男<input type="radio" name='sex' value='male' onChange={e => this.setState({sex:e.target.value})}/>
          女<input type="radio" name='sex' value='female' onChange={e => this.setState({sex:e.target.value})}/><br/>
          <button type='submit'>提交</button>
        </form>
      </div>
    )
  }
}
export default App

表单的radio通过受控组件来控制checked的状态改变来修改,这种方法比较麻烦,所以我们用 非受控组件 来写表单的radio事件

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.state = {
            sex:'male'
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let obj = this.state
    console.log(obj)
  }
  handleChange(e){
    this.setState({
      input:e.target.value
    })
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
                    男<input type="radio" name='sex' value='male' checked={this.state.sex === 'male' ? true : false} onChange={e => this.setState({sex:e.target.value})}/>
          女<input type="radio" name='sex' value='female' checked={this.state.sex === 'female' ? true : false} onChange={e => this.setState({sex:e.target.value})}/><br/>
          <button type='submit'>提交</button>
        </form>
      </div>
    )
  }
}
export default App

表单的checnkbox输入

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.state = {
            agree:true
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let obj = this.state
    console.log(obj)
  }
  handleChange(e){
    this.setState({
      input:e.target.value
    })
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
                    我已阅读并同意<input type="checkbox" value='agree' onChange={e =>this.setState({agree:!this.state.agree})}/><br/>
          <button type='submit'>提交</button>
        </form>
      </div>
    )
  }
}
export default App

checnkbox的多选

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.handleCheck = this.handleCheck.bind(this)
    this.state = {
            hobby:[]
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let obj = this.state
    console.log(obj)
  }
  handleChange(e){
    this.setState({
      input:e.target.value
    })
  }
  handleCheck(e){
    let hobby = this.state.hobby
    let value = e.target.value
    let index = hobby.indexOf(value)
    console.log(index)
    if(index === -1){
      hobby.push(value)
    }else{
      hobby.splice(index,1)
    }
    this.setState({hobby})
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)}>
                    兴趣爱好:<br/>
          篮球<input type="checkbox" value='basketball' onChange={this.handleCheck}/><br/>
          足球<input type="checkbox" value='football' onChange={this.handleCheck}/><br/>
          排球<input type="checkbox" value='paiqiu' onChange={this.handleCheck}/><br/>
          台球<input type="checkbox" value='taiqiu' onChange={this.handleCheck}/><br/>
          <button type='submit'>提交</button>
        </form>
      </div>
    )
  }
}
export default App

表单的重置:通过设置state为空来重置表单

import React from 'react'

class App extends React.Component {
  constructor(){
    super()
    this.state = {
      input:''
    }
  }
  handleSubmit(e){
    e.preventDefault()
    let obj = this.state
    console.log(obj)
  }
  handleReset(){
    this.setState({
      input:''
    })
  }
  render() {
    return (
      <div className="app">
        <form onSubmit={this.handleSubmit.bind(this)} onReset={this.handleReset.bind(this)}>
          <input type="text" value={this.state.input} onChange={e => this.setState({input:e.target.value})} />
          <button type='submit'>提交</button>
          <button type='reset'>重置</button>
        </form>
      </div>
    )
  }
}
export default App

处理多个输入

import React from 'react'

class Input extends React.Component {
  constructor(){
    super()
    this.state = {
      textarea:'',
      fruits:'banana'
    }
  }
  handleChange(type,e){
    this.setState({
      [type]:e.target.value
    })
  }
  render() {
    return (
      <div>
          <textarea
              cols="30"
              rows="10"
              value={this.state.textarea}
              onChange={this.handleChange.bind(this,'textarea')}>
            </textarea><br/>
          <select value={this.state.fruits} onChange={this.handleChange.bind(this,'fruits')}>
            <option value="apple">苹果</option>
            <option value="orange">橘子</option>
            <option value="banana">香蕉</option>
          </select><br/>
          <button onClick={() => console.log(this.state)}>提交</button>
      </div>
    )
  }
}
export default Input

注意:传入的type参数与对应state的名字

混合组件的优点

  1. 支持传入默认值;
  2. 可控:组件外部修改props可改变input组件的真实值及显示值;
  3. 非可控:输入框中输入值,可同时改变input组件的真实值及显示值。