狀態(tài)提升是什么意思? 一個最簡單的例子,就是如果兩個子組件需要利用到對方的狀態(tài)的話,那么這個時候我們就需要使用到狀態(tài)提升,具體的做法就是把兩個子組件的狀態(tài)寫到它們的父組件當(dāng)中,然后父組件把狀態(tài)傳遞到子組件的props中去,這樣子組件也相當(dāng)于有狀態(tài)。父組件相當(dāng)于是數(shù)據(jù)源,這樣的話,子組件是沒有控制權(quán)的,那么如果之前子組件的state是受到控制的怎么辦呢?就像我們之前說到的受控組件一樣,像:
<input value = {this.state.value} onChange = {this.handleChange}/>
那我們就得在父組件中寫出子組件的處理函數(shù),并在處理函數(shù)中更改父組件的state
來看一個完整的狀態(tài)提升的例子:
先寫一個溫度輸入組件:
class TemperatureInput extends React.Component {
state = {
temperature: ''
};
handleChange = (e) => {
this.setState({
temperature : e.target.value
})
};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[this.props.scale]}:</legend>
<input type="number" value={this.state.temperature} onChange={this.handleChange}
</fieldset>
)
}
}
這個組件就是一個普通的受控組件,有state和props以及處理函數(shù)。
我們在寫另一個組件:
class Calculator extends React.Component {
render () {
return (
<div>
<TemperatureInput scale='c'/>
<TemperatureInput scale='f'/>
</div>
)
}
}
這個組件現(xiàn)在沒有什么存在的價值,我們僅僅是給兩個溫度輸入組件提供一個父組件,以便我們進(jìn)行后續(xù)的狀態(tài)提升。
現(xiàn)在我們看看網(wǎng)頁的樣子:

我們可以輸入攝氏度和華氏度,但是我們現(xiàn)在想要讓這兩個溫度保持一致,就是我們?nèi)绻斎霐z氏度,那么下面的華氏度可以自動算出來,如果我們輸入華氏度,那么攝氏度就可以自動算出來。
那么我們按照現(xiàn)在這種結(jié)構(gòu)的話,是非常難以實(shí)現(xiàn)的,因?yàn)槲覀冎肋@兩個組件之間沒有任何關(guān)系,它們之間是不知道對方的存在,所以我們需要把它們的狀態(tài)進(jìn)行提升,提升到它們的父組件當(dāng)中。
那我們看看如何做修改,首先把子組件(溫度輸入組件)的狀態(tài)(state)全部刪除,看看是什么樣子:
class TemperatureInput extends React.Component {
handleChange = (e) => {
};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[this.props.scale]}:</legend>
<input type="number" value={this.props.temperature} onChange={this.handleChange}/>
</fieldset>
)
}
}
可以看到所有與state有關(guān)的東西全部刪掉了,然后input的value也變成了props,通過父組件傳入。那么現(xiàn)在這個溫度輸入組件其實(shí)就是一個受控組件了,仔細(xì)回憶一下我們之前講的受控組件,看看是不是這樣意思?
我們通常會在受控組件發(fā)生改變的時候傳入一個onChange函數(shù)來改變受控組件的狀態(tài),那么我們這里也是一樣,我們通過給 溫度輸入組件 傳入某個函數(shù)來讓 溫度輸入組件 中的input發(fā)生變化的時候調(diào)用,當(dāng)然這個函數(shù)我們可以隨意命名,假如我們這里叫做onTemperatureChange函數(shù),那么我們繼續(xù)修改子組件:
class TemperatureInput extends React.Component {
handleChange = (e) => {
this.props.onTemperatureChange(e.target.value);
};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[this.props.scale]}:</legend>
<input type="number" value={this.props.temperature} onChange={this.handleChange}/>
</fieldset>
)
}
}
好了,我們的子組件差不多就是這樣了,當(dāng)然我們可以省略那個handleChange函數(shù),因?yàn)榭梢钥吹竭@個函數(shù)就是調(diào)用了一下那個props里的函數(shù),所以我們完全把input的onChange這么寫
<input type="number" value={this.props.temperature} onChange={this.props.onTemperatureChange}/>這么寫的話注意onTemperatrueChange函數(shù)的參數(shù)是那個事件,而不是我這里寫的e.target.value。
再看看我們的父組件如何修改,我們首先補(bǔ)上state,以及子組件對應(yīng)的onChange處理方法,以及子組件的值。寫好之后大概是這個樣子:
class Calculator extends React.Component {
state = {
celsius: '',
fahrenheit: ''
};
onCelsiusChange = (value) => {
this.setState({
celsius: value,
fahrenheit: tryConvert(value, toFahrenheit)
});
};
onFahrenheitChange = (value) => {
this.setState({
celsius: tryConvert(value, toCelsius),
fahrenheit: value
});
};
render() {
return (
<div>
<TemperatureInput scale='c' temperature={this.state.celsius}
onTemperatureChange={this.onCelsiusChange}/>
<TemperatureInput scale='f' temperature={this.state.fahrenheit}
onTemperatureChange={this.onFahrenheitChange}/>
</div>
)
}
}
這里我們省略的攝氏度與華氏度的轉(zhuǎn)換函數(shù),比較簡單,大家自行搜索方法。
最后加上我們的 水是否能夠燒開的組件。

