侧边栏壁纸
博主头像
woku博主等级

成功的路上并不拥挤

  • 累计撰写 50 篇文章
  • 累计创建 13 个标签
  • 累计收到 3 条评论

受控组件与非受控组件

woku
2022-08-08 / 0 评论 / 0 点赞 / 83 阅读 / 6,774 字

受控组件

概念

受控组件,字面意思就是受到控制的组件
满足2个条件:
1.表单的数据源受到state的控制,也就是说state是表单的唯一数据源 value=

2.控制表单操作并且同步state onChange=


<p>
  姓名:
  <input type="text"  id="" value={this.state.name} onChange={this.changeNameHandle.bind(this)}/>
</p>

上面的这种组件就是受控组件
满足1:value是来自state中的数据
满足2:提供了onChange事件,并同步state

简单使用

input type="password" --- textareaselect

// 受控组件:受到控制的组件。
// 1.表单的数据源受到state的控制,也就是说state是表单的唯一数据源  value={this.state.XXX}
// 2.控制表单操作并且同步state   onChange={this.XXX}

class MyForm extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    name: '',
    password: '',
    intro: '',
    city: ''
  }
  changeNameHandle(e) {
    this.setState({
      name: e.target.value
    })
  }
  changePassHandle(e) {
    this.setState({
      password: e.target.value
    })
  }
  changeIntroHandle(e) {
    this.setState({
      intro: e.target.value
    })
  }
  changeCityHandle(e) {
    this.setState({
      city: e.target.value
    })
  }
  render() {
    return (
      <div>
        <p>
          姓名:
          <input type="text"  id="" value={this.state.name} onChange={this.changeNameHandle.bind(this)}/>
        </p>
        <p>密码
          <input type="password"  id=""  value={this.state.password} onChange={this.changePassHandle.bind(this)}/>
        </p>
        <p>
          介绍
          <textarea name="" id="" cols="30" rows="10" value={this.state.intro} onChange={this.changeIntroHandle.bind(this)}></textarea>
        </p>
        <p>
          城市
          <select name="" id="" value={this.state.city} onChange={this.changeCityHandle.bind(this)}>
            <option value="changsha">长沙</option>
            <option value="shenzhen">深圳</option>
            <option value="beijing">北京</option>
          </select>
        </p>
      </div>
    )
  }
}

ReactDOM.render(<MyForm />, document.getElementById('app'))

上面代码中,changeNameHandlechangePassHandlechangeIntroHandlechangeCityHandle里面的逻辑都是类似的。我们可以把封装成一个统一的函数,
通过name这个属性来区分是要修改哪个数据

class MyForm extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    name: '',
    password: '',
    intro: '',
    city: ''
  }
  changeHandle(e) {
    this.setState({
      [e.target.name]: e.target.value
    })
  }
  doSubmit(e) {
    e.preventDefault()
    const {
      name,
      password,
      intro,
      city
    } = this.state
    console.log(name, password, intro, city)
  }
  render() {
    return (
      <form>
        <p>
          姓名:
          <input type="text" name="name" id="" value={this.state.name} onChange={this.changeHandle.bind(this)}/>
        </p>
        <p>密码
          <input type="password" name="password" id=""  value={this.state.password} onChange={this.changeHandle.bind(this)}/>
        </p>
        <p>
          介绍
          <textarea name="intro" id="" cols="30" rows="10" value={this.state.intro} onChange={this.changeHandle.bind(this)}></textarea>
        </p>
        <p>
          城市
          <select name="city" id="" value={this.state.city} onChange={this.changeHandle.bind(this)}>
            <option value="changsha">长沙</option>
            <option value="shenzhen">深圳</option>
            <option value="beijing">北京</option>
          </select>
        </p>
        <p>
          <button type="submit" onClick={this.doSubmit.bind(this)}>提交</button>
        </p>
      </form>
    )
  }
}

ReactDOM.render(<MyForm />, document.getElementById('app'))
  • input type="radio" --- input type="checkbox"
class MyForm extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    isWeb: true,
    hobbies: []
  }
  handleIsWeb(isWeb) {
    this.setState({
      isWeb
    })
  }
  handelHobbiesChange(e) {
    if (e.target.checked) {
      this.setState({
        hobbies: [...this.state.hobbies, e.target.value]
      })
    } else {
      this.setState({
        hobbies: this.state.hobbies.filter(x => x !== e.target.value)
      })
    }
  }

  doSubmit(e) {
    e.preventDefault()
    const {
     isWeb,
     hobbies
    } = this.state
    console.log(isWeb, hobbies)
  }
  render() {
    return (
      <form>
        <p>专业:
           前端 <input type="radio" name="professional" checked={this.state.isWeb} onChange={this.handleIsWeb.bind(this, true)}></input>
           后端 <input type="radio" name="professional" onChange={this.handleIsWeb.bind(this, false)}></input>
        </p>
        <p>
          <input type="checkbox" value="coding" name="hobbies" onChange={this.handelHobbiesChange.bind(this)}/>敲代码|
          <input type="checkbox" value="studying" name="hobbies"  onChange={this.handelHobbiesChange.bind(this)}/>学习|
          <input type="checkbox" value="reading" name="hobbies"  onChange={this.handelHobbiesChange.bind(this)}/>阅读|
        </p>
        <p>
          <button type="submit" onClick={this.doSubmit.bind(this)}>提交</button>
        </p>
      </form>
    )
  }
}

ReactDOM.render(<MyForm />, document.getElementById('app'))

将hobbies列表作为一个数据渲染

class MyForm extends React.Component {
  constructor(props) {
    super(props)
  }
  state = {
    isWeb: true,
    hobbies: ['coding'],
    hobbiesData: [{
      value: 'coding',
      label: '敲代码'
    }, {
      value: 'studying',
      label: '学习'
    }, {
      value: 'reading',
      label: '阅读'
    }]
  }
  handleIsWeb(isWeb) {
    this.setState({
      isWeb
    })
  }
  handelHobbiesChange(e) {
    if (e.target.checked) {
      this.setState({
        hobbies: [...this.state.hobbies, e.target.value]
      })
    } else {
      this.setState({
        hobbies: this.state.hobbies.filter(x => x !== e.target.value)
      })
    }
  }

  doSubmit(e) {
    e.preventDefault()
    const {
     isWeb,
     hobbies
    } = this.state
    console.log(isWeb, hobbies)
  }
  render() {
    return (
      <form>
        <p>专业:
           前端 <input type="radio" name="professional" checked={this.state.isWeb} onChange={this.handleIsWeb.bind(this, true)}></input>
           后端 <input type="radio" name="professional" onChange={this.handleIsWeb.bind(this, false)}></input>
        </p>
        <p>
          {
            this.state.hobbiesData.map(x => (
              <span key={x.value}>
                <input type="checkbox" name="hobbies" checked={this.state.hobbies.includes(x.value)} value={x.value} onChange={this.handelHobbiesChange.bind(this)}/> {x.label}
              </span>
            ))
          }
        </p>
        <p>
          <button type="submit" onClick={this.doSubmit.bind(this)}>提交</button>
        </p>
      </form>
    )
  }
}

ReactDOM.render(<MyForm />, document.getElementById('app'))

非受控组件

非受控组件借助于ref,使用原生DOM方式来获取DOM元素。(相当于 vue中的refrefs)

  • 调用React.createRef来创建一个ref
import React from "react";

const { Component } = require("react");

class App extends Component {
    divRef = React.createRef()
}

  • 将创建好的ref对象添加到相应的DOM元素上
import React from "react";

const { Component } = require("react");

class App extends Component {
    divRef = React.createRef()
    render () {
       return (
        <div>
            <div ref={this.divRef}>
              <button onClick={this.btnHandle.bind(this)}>获取ref非受控组件元素</button>
            </div>
        </div>
       )
    }
}

  • 通过ref对象获取相应DOM元素

创建的ref对象的current来获取

import React from "react";

const { Component } = require("react");

class App extends Component {
    divRef = React.createRef()
    btnHandle() {
       console.log(this.divRef.current)
    }
    render () {
       return (
        <div>
            <div ref={this.divRef}>
              <button onClick={this.btnHandle.bind(this)}>获取ref非受控组件元素</button>
            </div>
        </div>
       )
    }
}

0

评论区