React--受控组件和非受控组件

受控组件

  • React 中,HTML 表单的处理方式和普通 DOM 元素不太一样,表单元素(如 <input><select>等)通常需要维护自己的 state,并根据输入进行更新
  • React 中的可变状态通常保存在组件的 state 中,并且只能通过使用 setState() 来更新

受控组件的由来

  • 将两者结合起来,使 Reactstate 成为"唯一数据源"
  • 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作
  • React 以这种方式控制取值的表单元素称为"受控组件"

React推荐使用受控组件来处理表单数据 ,因为受控组件的数据由 Reactstate 驱动

jsx 复制代码
 <input type="text" value={username} onChange={e => this.inputChange(e)} />
 ​
 inputChange(event) {
   this.setState({ username: event.target.value})
 }
  • 例如上面 input 元素,设置了 value 属性,那必须对其 onChange 事件进行处理,保持 state 的更新
  • 若不处理 onChange 事件,输入框则无法输入内容,这保证了 Reactstate 成为唯一数据源

input处理多输入

  • 当需要处理多个 input 元素时,可以给每个元素添加 name 属性,
  • 然后让处理函数根据 event.target.name 的值选择要执行的操作
jsx 复制代码
 this.state = {
   username: '';
   password: ''
 }
 ​
 <label htmlFor="username">
   用户:
   <input type="text" id="username" name="username" value={username}
     onChange={e => this.handleInputChange(e)}
   />
 </label>
 <label htmlFor="password">
   密码:
   <input type="text" id="password" name="password" value={password}
     onChange={e => this.handleInputChange(e)}
   />
 </label>
 ​
 handleInputChange(event) {
   this.setState({
     // 使用计算属性名称更改state
     [event.target.name]: event.target.value
   });
 }

checkbox单选和多选

  • 当使用 checkbox 时,需要从 event.target.checked 上获取最新的布尔值
  • 使用单选框受控组件
jsx 复制代码
 this.state = {
   isAgree: false;
 }
 ​
 <label htmlFor="agree">
   <input type="checkbox" id="agree" checked={isChecked} 
   onChange={e => this.handleCheckChange(e)} 
   /> 同意
 </label>
 ​
 handleCheckChange(event) {
   this.setState({ 
     isAgree: event.target.checked
   })
 }
  • 使用多选框受控组件
jsx 复制代码
 this.state = {
   hobbies: [
     { value:'sing', text:'唱', isChecked: false },
     { value:'dance', text:'跳', isChecked: false },
     { value:'rap', text:'rap', isChecked: false },
   ]
 }
 ​
 <div>
   {
     hobbies.map((item, i)=>{
     return (
       <label htmlFor={item.value} key={item.value}>
         <input type="checkbox" id={item.value} checked={item.isChecked}
           onChange={e => this.handleHobbiesChange(e, i)}
         /> 
         {item.text}
       </label>
       )
     }) 
   }
 </div>
 ​
 handleHobbiesChange(event, index) {
   const hobbies = [...this.state.hobbies]
   hobbies[index].isChecked = event.target.checked
   this.setState({ hobbies })
 }

select单选和多选

  • select 受控组件和 input 类似,React 并不会使用 selected 属性,而是使用根据 <select> 标签上使用 value 属性
  • select 单选使用
javascript 复制代码
 this.state = {
   fruit: 'apple'
 }
 ​
 <select value={fruit} onChange={e => this.handleSelectChange(e)}>
   <option value="apple">苹果</option>
   <option value="mango">芒果</option>
   <option value="banana">香蕉</option>
 </select>
 ​
 handleSelectChange(event) {
   this.setState({
     fruit: event.target.value
   });
 }
  • select 多选使用,在多选的情况下,<select> 根标签的 value 需要绑定一个数组,并且在 onChange 中需要通过 event.target.selectedOptions 获取当前选中的所有项
jsx 复制代码
 this.state = {
   fruit: ['apple']
 }
 ​
 <select multiple value={fruit} onChange={e => this.handleSelectChange(e)}>
   <option value="apple">苹果</option>
   <option value="mango">芒果</option>
   <option value="banana">香蕉</option>
 </select>
 ​
 handleSelectChange(event) {
   const options = Array.from(event.target.selectedOptions, item => item.value)
   this.setState({ fruit: options });
 }

非受控组件

  • React 推荐大多数情况下使用受控组件来处理表单数据,另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理
  • 如果要使用非受控组件中的数据,那么需要使用 refDOM 节点中获取表单数据,并且使用 defaultValue 属性设置其默认值
jsx 复制代码
 import { PureComponent, createRef } from 'react'
 ​
 class App extends PureComponent {
   constructor() {
     super()
     this.state = {
       nickname: "tony"
     }
     this.inputRef = createRef()
   }
 ​
   componentDidMount() {
     this.inputRef.current.addEventListener('input', (event)=>{
       this.setState({ nickname: event.target.value })
     })
 ​
   }
 ​
   render() {
     const { nickname } = this.state
     return <input type="text" ref={this.inputRef} defaultValue={nickname}/>
   }
 }
  • 如果是 checkboxradio,需要使用 defaultChecked
html 复制代码
 <input type="checkbox" ref={this.inputRef} defaultChecked={nickname}/>
 
 <input type="radio" ref={this.inputRef} defaultChecked={nickname}/>
  • 开发中更推荐受控组件,让数据交由 Reactstate 管理
相关推荐
知识分享小能手4 分钟前
Bootstrap 5学习教程,从入门到精通,Bootstrap 5 表单验证语法知识点及案例代码(34)
前端·javascript·学习·typescript·bootstrap·html·css3
一只小灿灿18 分钟前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉
前端小趴菜0530 分钟前
react状态管理库 - zustand
前端·react.js·前端框架
Jerry Lau1 小时前
go go go 出发咯 - go web开发入门系列(二) Gin 框架实战指南
前端·golang·gin
我命由我123451 小时前
前端开发问题:SyntaxError: “undefined“ is not valid JSON
开发语言·前端·javascript·vue.js·json·ecmascript·js
0wioiw01 小时前
Flutter基础(前端教程③-跳转)
前端·flutter
落笔画忧愁e2 小时前
扣子Coze纯前端部署多Agents
前端
海天胜景2 小时前
vue3 当前页面方法暴露
前端·javascript·vue.js
GISer_Jing2 小时前
前端面试常考题目详解
前端·javascript
Boilermaker19923 小时前
【Java EE】SpringIoC
前端·数据库·spring