受控组件
- 在
React中,HTML表单的处理方式和普通DOM元素不太一样,表单元素(如<input>、<select>等)通常需要维护自己的state,并根据输入进行更新 React中的可变状态通常保存在组件的state中,并且只能通过使用setState()来更新
受控组件的由来
- 将两者结合起来,使
React的state成为"唯一数据源" - 渲染表单的
React组件还控制着用户输入过程中表单发生的操作 - 被
React以这种方式控制取值的表单元素称为"受控组件"
React推荐使用受控组件来处理表单数据 ,因为受控组件的数据由React的state驱动
jsx
<input type="text" value={username} onChange={e => this.inputChange(e)} />
inputChange(event) {
this.setState({ username: event.target.value})
}
- 例如上面
input元素,设置了value属性,那必须对其onChange事件进行处理,保持state的更新 - 若不处理
onChange事件,输入框则无法输入内容,这保证了React的state成为唯一数据源

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节点来处理- 如果要使用非受控组件中的数据,那么需要使用
ref从DOM节点中获取表单数据,并且使用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}/>
}
}
- 如果是
checkbox和radio,需要使用defaultChecked
html
<input type="checkbox" ref={this.inputRef} defaultChecked={nickname}/>
<input type="radio" ref={this.inputRef} defaultChecked={nickname}/>
- 开发中更推荐受控组件,让数据交由
React的state管理