受控元件與非受控元件:是否受狀態控制。
1.用受控元件實現雙向資料繫結
我們來實現一個react的雙向資料繫結
讓輸入框輸入值,下面的顯示跟著變化
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
class Input extends Component{
constructor(){
super();
this.state={val:''}
}
render(){
return (<div>
<input type="text" value={this.state.val}/>
{this.state.val}
</div>)
}
}
ReactDOM.render(<Input/>, document.querySelector('#root'));
複製程式碼
但是結果和我們想象的不一樣:輸入框不能輸入值。這是因為input的value取的是state中的val。但是val的值一直是空。 改變state的唯一方式setState
- 受狀態控制的元件,必須要有onChange方法,否則不能使用.
- 受控元件可以賦予預設值(官方推薦使用受控元件)
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
class Input extends Component{
constructor(){
super();
this.state={val:'100'}
}
handleChange=(e)=>{//e是事件源
let val=e.target.value;
this.setState({val});
}
render(){
return (<div>
<input type="text" value={this.state.val} onChange={this.handleChange}/>
{this.state.val}
</div>)
}
}
ReactDOM.render(<Input/>, document.querySelector('#root'));
複製程式碼
簡單功能實現,輸入框值,與顯示值統一。這就是受控元件,受狀態控制。
2.受控元件公用方法的狀態控制
兩個輸入框實現求和功能,如果使用兩個onchange事件,會造成程式碼的冗餘。我們現在把他們合在一起。
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
class Sum extends Component{
constructor(){
super();
this.state={a:1,b:1}
}
//key表示的當前狀態改的是哪一個
//e表示的是事件源
handleChange=(key,e)=>{//處理多個輸入框的值對映到狀態的方法
let val=e.target.value;
this.setState({[key]:val});
}
render(){
return (<div>
<input type="text" value={this.state.a} onChange={(e)=>{
this.handleChange('a',e)
}}/>
<input type="text" value={this.state.b} onChange={(e)=>{
this.handleChange('b',e)
}}/>
{this.state.a+this.state.b}
</div>)
}
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼
這樣就可以通過一個方法實現兩個onchange事件的功能,不過上面是兩個字串的拼接,需要轉為數字再相加,在這就不做了。
3.非受控元件(不受狀態控制)
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
//輸入框value值不受狀態控制,不能初始化預設值
class Sum extends Component{
constructor(){
super();
this.state={result:''}
}
//通過ref設定的屬性,可以通過this.refs獲取到對應的dom元素
handleChange=()=>{
let result=this.refs.a.value+this.refs.b.value;
this.setState({result});
}
render(){
return (<div onChange={this.handleChange}>//運用冒泡的機制不在兩個input中新增onchange事件
<input type="text" ref="a"/>
<input type="text" ref="b"/>
{this.state.result}
</div>)
}
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼
上面這種實現方式,兩個輸入框不受狀態的控制。通過操作dom獲取到value值,然後進行相加。這就是非受控元件,他與受控元件的區別就是不可以給預設值。
ref的另外一種實現方式(推薦)
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
import ErrorBoundary from './components/ErrorBoundary';
import Counter from "./components/Counter";
import Todos from "./components/Todos";
//輸入框value值不受狀態控制,不能初始化預設值
class Sum extends Component{
constructor(){
super();
this.state={result:''}
}
//通過ref設定的屬性,可以通過this.refs獲取到對應的dom元素
handleChange=()=>{
let result=this.refs.a.value+this.b.value;
this.setState({result});
}
render(){
return (<div onChange={this.handleChange}>//運用冒泡的機制不在兩個input中新增onchange事件
<input type="text" ref="a"/>
//x代表真實的dom ,把元素掛載到了當前例項上
<input type="text" ref={x=>this.b=x}/>
{this.state.result}
</div>)
}
}
ReactDOM.render(<Sum/>, document.querySelector('#root'));
複製程式碼
第二個輸入框中ref給了一個箭頭函式,x代表真實的dom,把真實dom賦值給當前例項中。