2022-11-24 11:15:20 +08:00

364 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 表单
本章主要包含以下内容:
- 受控组件
- 非受控组件
## 受控组件
无论是学习 *Vue*,还是 *React*,最重要的是要转换思想,这一步非常重要,往往也比较困难。
在以前 *jQuery* 时代,开发人员需要获取到 *DOM* 节点,然后进行操作。而在现代前端开发中,采用的是 *MVVM* 的模式,将视图和视图模型进行绑定,视图模型的改变,会自然的带来视图的改变。开发人员需要专注在视图模型上面。
因此,这里所谓的受控组件,本质上其实就是将表单中的控件和视图模型(状态)进行绑定,之后都是针对状态进行操作。
下面,我们来看一些具体的案例:
- 一个基本的受控组件
```react
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;
```
- 对用户输入的内容进行限制
```react
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;
```
- 文本域
```react
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;
```
- 多选框
```react
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;
```
- 下拉列表
```react
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* 方案进行处理,此时替代的方案就是非受控组件。
- 非受控组件基本示例
```react
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;
```
- 非受控组件的默认值
```react
<div>
{/* 一旦你用了 valueReact 会认为你这是一个受控组件 */}
{/* 如果想要给默认值,使用 defaultValue */}
<input type="text" ref={this.inputCon} defaultValue="123"/>
<button onClick={this.clickHandle}>获取用户输入的内容</button>
</div>
```
- 文件上传
```react
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/*