Skip to content

表单

本章主要包含以下内容:

受控组件#

无论是学习 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/