React 表单受控和非受控组件的基本使用
在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state。
受控组件
渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。
被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
对于受控组件来说,输入的值始终由 React 的 state 驱动。
不同的表单项数据处理(受控组件)
:
- input、select和textarea处理方式一样
- 将state值绑定到表单输入域value属性上
- 监听表单输入域onChange事件,事件函数中动态更新状态值
input
:
<div>
{/*label标签的for属性需要修改为htmlFor,因为for是关键字*/}
<label htmlFor='uname'>用户名:</label>
<input value={this.state.uname} onChange={this.handleUname} type="text" id="uname"/>
</div>
handleUname = (e) => {
// 监听表单输入域的值的变化
this.setState({
uname: e.target.value
})
}
radio
:
<div>
<label>性别:</label>
<label htmlFor="male">男</label>
<input checked={gender === '1'? true: false} onChange={this.handleGender} value='1' type="radio" name='gender' id="male"/>
<label htmlFor="female">女</label>
<input checked={gender === '2'? true: false} onChange={this.handleGender} value='2' type="radio" name='gender' id="female"/>
</div>
handleGender = (e) => {
// 监听radio值的变化
this.setState({
gender: e.target.value
})
}
select
:
<div>
<label htmlFor="job">工作:</label>
<select id="job" value={job} onChange={this.handleItem}>
<option value="1">程序猿</option>
<option value="2">产品狗</option>
<option value="3">测试</option>
</select>
</div>
handleItem = (e) => {
// 监听select值的变化
this.setState({
[e.target.id]: e.target.value
})
}
checkbox
:
<div>
<label>兴趣:</label>
<label htmlFor="coding">写代码</label>
<input checked={favour.includes('coding')} onChange={this.handleFavour} value='coding' name='favour' type="checkbox" id="coding"/>
<label htmlFor="singing">唱歌</label>
<input checked={favour.includes('singing')} onChange={this.handleFavour} value='singing' name='favour' type="checkbox" id="singing"/>
<label htmlFor="dancing">跳舞</label>
<input checked={favour.includes('dancing')} onChange={this.handleFavour} value='dancing' name='favour' type="checkbox" id="dancing"/>
</div>
handleFavour = (e) => {
// 监听兴趣的选择
// console.log(e.target.value)
// 当前点击的选框的值
let v = e.target.value
// 如果favour数组中包含v这个值,需要删除,如果不包含,就添加进去
let newFavour = [...this.state.favour]
let flag = newFavour.some(item => item === v)
if (flag) {
// 已经存在,那就删除该值
let index = newFavour.findIndex(item => item === v)
newFavour.splice(index, 1)
} else {
// 尚不存在,那就添加该值
newFavour.push(v)
}
this.setState({
favour: newFavour
})
}
textarea
:
<div>
<label htmlFor="desc">个人介绍:</label>
<textarea value={desc} onChange={this.handleItem} id="desc" cols="30" rows="10"></textarea>
</div>
handleItem = (e) => {
this.setState({
[e.target.id]: e.target.value
})
}
非受控组件
非受控组件用法:
- 创建ref实例对象
- 把ref对象关联到标签上
- 通过ref对象的current属性可以得到原生DOM对象
非受控组件的应用场景:
- 获取输入域的焦点
- 文件上传获取文件信息
-
通过ref实例对象current属性可以得到原生DOM对象,(类似于vue中ref,本质上就是直接操作DOM)。
-
可以使用defaultValue指定表单的默认值
// 构造函数 this.textInput = React.createRef(); // 标签中 <input type="text" ref={this.textInput} /> // 使用 this.textInput.current.focus();
-
文件上传应用
this.fileRef = React.createRef(); let fileInfo = this.fileRef.current.files[0]; <input type="file" id="file" ref={this.fileRef}/>
示例代码
:
import React from 'react'
class FormTest extends React.Component {
inputRef = React.createRef()
fileRef = React.createRef()
handleClick = () => {
// let v = this.inputRef.current.value
// console.log('获取表单数据:' + v)
// 获取选中的文件信息
let file = this.fileRef.current.files[0]
// 选中文件之后,下一步就是把file对象提交到后台接口即可
console.log(file)
}
componentDidMount () {
// 获取输入域的焦点
this.inputRef.current.focus()
}
render () {
return (
<div>
<h1>非受控组件用法</h1>
<hr/>
<label htmlFor="uname">用户名</label>
<input ref={this.inputRef} type="text" id="uname"/>
<hr/>
<div>
<input ref={this.fileRef} type="file" />
</div>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}
export default FormTest