写在前面
React 中受控组件和非受控组件的概念是针对于表单元素的。
表单元素的工作方式和其他 DOM 元素有些不同,简单来说,其他 DOM 元素的 state 数据都是由开发者直接控制和维护的,但是表单元素的 state 是由表单自己维护的,用户通过输入的方式改变表单的 state 数据。
表单数据默认是由自己维护的,那么能否将表单的数据交给开发者维护呢?这就衍生出受控组件和非受控组件的概念。
官方解释:React 受控组件 和 React 非受控组件
1. 受控组件
受控组件,顾名思义,就是表单组件数据受开发者的控制,也就是说开发者可以通过 JavaScript 对页面中表单的内容进行改变和控制。
<input value={x} onChange={fn}/>
class App extends React.Component{
constructor(props){
super(props)
this.state = {val: ''}
}
handleChange = (e)=>{
this.setState({val: e.target.value})
}
handleSubmit = (e)=>{
e.preventDefault();
console.log(this.state.val)
}
handleClick = ()=>{
this.setState({val: 'vin'})
}
render(){
return (
<div>
我是App组件
<form onSubmit={this.handleSubmit}>
<label>
名字:<input type="text" value={this.state.val} onChange={this.handleChange}/>
</label>
<label>
<input type="submit"/>
</label>
</form>
<button onClick={this.handleClick}>改变名字为 vin</button>
</div>
)
}
}
自定义表单组件的受控组件是一样的控制方式
const MyInput = (props)=>{
return (
<form onSubmit={props.onSubmit}>
<label>
名字:<input type="text" value={props.value} onChange={props.onChange}/>
</label>
<label>
<input type="submit"/>
</label>
</form>
)
}
class App extends React.Component{
constructor(props){
super(props)
this.state = {val: ''}
}
handleChange = (e)=>{
this.setState({val: e.target.value})
}
handleSubmit = (e)=>{
e.preventDefault();
console.log(this.state.val)
}
handleClick = ()=>{
this.setState({val: 'vin'})
}
render(){
return (
<div>
我是App组件
<MyInput value={this.state.val} onChange={this.handleChange} onSubmit={this.handleSubmit}/>
<button onClick={this.handleClick}>改变名字为 vin</button>
</div>
)
}
}
2. 非受控组件
非受控组件的数据由表单DOM元素自己维护。
非受控组件中若想设置初始值,不能使用 value 属性了,而是使用 defaultValue 属性仅仅进行数据初始化。
通过为表单元素添加 ref 属性的方式访问表单内的数据。
<input defaultValue={x} ref={input}/>
class App extends React.Component{
constructor(props){
super(props)
this.state = {val: ''}
this.myRef = React.createRef()
}
handleSubmit = (e)=>{
e.preventDefault();
console.log(this.myRef.current.value)
}
render(){
return (
<div>
我是App组件
<form onSubmit={this.handleSubmit}>
<label>
名字:<input type="text" defaultValue={this.state.val} ref={this.myRef}/>
</label>
<label>
<input type="submit"/>
</label>
</form>
</div>
)
}
}