本章主要包含以下内容:
- 受控组件
- 非受控组件
受控组件#
无论是学习 Vue,还是 React,最重要的是要转换思想,这一步非常重要,往往也比较困难。
在以前 jQuery 时代,开发人员需要获取到 DOM 节点,然后进行操作。而在现代前端开发中,采用的是 MVVM 的模式,将视图和视图模型进行绑定,视图模型的改变,会自然的带来视图的改变。开发人员需要专注在视图模型上面。
因此,这里所谓的受控组件,本质上其实就是将表单中的控件和视图模型(状态)进行绑定,之后都是针对状态进行操作。
下面,我们来看一些具体的案例:
- 一个基本的受控组件
import React from 'react'
// 类组件class App extends React.Component { state = { value: '', }
handleChange = (e) => { this.setState({ value: e.target.value, }) }
clickHandle = () => { // 提交整个表单 console.log(`你要提交的内容为:${this.state.value}`) }
render() { return ( <div> <input type="text" value={this.state.value} onChange={this.handleChange} /> <button onClick={this.clickHandle}>提交</button> </div> ) }}
export default App- 对用户输入的内容进行限制
import React from 'react'
// 类组件class App extends React.Component { state = { value1: '', value2: '', }
handleChange = (e) => { const name = e.target.name switch (name) { case 'one': { // 用户输入的是第一个输入框 // 只能输入大写 this.setState({ value1: e.target.value.toUpperCase(), }) break } case 'two': { // 用户输入的是第二个输入框 // 只能输入数字 const newValue = e.target.value .split('') .map((item) => { if (!isNaN(item)) { return item } }) .join('') this.setState({ value2: newValue, }) break } } }
clickHandle = () => { // 提交整个表单 console.log(`你要提交的内容为:${this.state.value}`) }
render() { return ( <div> <input type="text" name="one" value={this.state.value1} onChange={this.handleChange} placeholder="自动转为大写" /> <input type="text" name="two" value={this.state.value2} onChange={this.handleChange} placeholder="只能输入数字" /> <button onClick={this.clickHandle}>提交</button> </div> ) }}
export default App- 文本域
import React from 'react'
// 类组件class App extends React.Component { state = { value: '', }
handleChange = (e) => { this.setState({ value: e.target.value, }) }
clickHandle = () => { // 提交整个表单 console.log(`你要提交的内容为:${this.state.value}`) }
render() { return ( <div> <textarea cols="30" rows="10" value={this.state.value} onChange={this.handleChange} /> <button onClick={this.clickHandle}>提交</button> </div> ) }}
export default App- 多选框
import React from 'react'
// 类组件class App extends React.Component { state = { checkBoxs: [ { content: 'html', checked: false }, { content: 'css', checked: false }, { content: 'js', checked: false }, { content: 'vue', checked: false }, { content: 'react', checked: false }, ], }
handleChange = (index) => { const arr = [...this.state.checkBoxs] arr[index].checked = !arr[index].checked this.setState({ checkBoxs: arr, }) }
clickHandle = () => { // 提交整个表单 console.log(this.state.checkBoxs) }
render() { return ( <div> <div> {this.state.checkBoxs.map((item, index) => ( <div key={index}> <input type="checkbox" value={item.content} checked={item.checked} onChange={() => this.handleChange(index)} /> <span>{item.content}</span> </div> ))} </div> <button onClick={this.clickHandle}>提交</button> </div> ) }}
export default App- 下拉列表
import React from 'react'
// 类组件class App extends React.Component { state = { value: 'html', }
handleChange = (e) => { this.setState({ value: e.target.value, }) }
clickHandle = () => { // 提交整个表单 console.log(this.state.value) }
render() { return ( <div> <select value={this.state.value} onChange={this.handleChange}> <option value="html">HTML</option> <option value="css">CSS</option> <option value="js">JS</option> <option value="vue">Vue</option> <option value="react">React</option> </select> <button onClick={this.clickHandle}>提交</button> </div> ) }}
export default App非受控组件#
大多数情况下,在 React 中推荐使用受控组件来对表单进行操作,这样能够对表单控件的数据进行一个统一管理。
但是在某些特殊情况下,需要使用以前传统的 DOM 方案进行处理,此时替代的方案就是非受控组件。
- 非受控组件基本示例
import React from 'react'
// 类组件class App extends React.Component { constructor() { super() // 创建了一个 ref,回头我们就可以获取到和该 ref 绑定了的 DOM 节点 this.inputCon = React.createRef() }
clickHandle = () => { // 通过 this.inputCon.current 可以获取到 input DOM 节点 console.log(this.inputCon.current.value) }
render() { return ( <div> <input type="text" ref={this.inputCon} /> <button onClick={this.clickHandle}>获取用户输入的内容</button> </div> ) }}
export default App- 非受控组件的默认值
<div> {/* 一旦你用了 value,React 会认为你这是一个受控组件 */} {/* 如果想要给默认值,使用 defaultValue */} <input type="text" ref={this.inputCon} defaultValue="123" /> <button onClick={this.clickHandle}>获取用户输入的内容</button></div>- 文件上传
import React from 'react'
// 类组件class App extends React.Component { constructor() { super() // 创建 ref 的时候,命名一般采用 xxxRef 结尾 this.uploadRef = React.createRef() }
clickHandle = () => { // 通过 this.uploadRef.current 可以获取到 input DOM 节点 console.log(this.uploadRef.current.files) }
render() { return ( <div> <input type="file" ref={this.uploadRef} /> <button onClick={this.clickHandle}>获取用户输入的内容</button> </div> ) }}
export default App关于受控组件和非受控组件,可以参阅:https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/