10. react - 状态提升
1. 什么是状态提升:
状态提升是指,公共父组件统一管理子组件状态的过程。
2. 为什么要做状态提升:
当两个子组件渲染同一个数据的不同状态时,并且要求两个子组件数据同步变化,子组件之间不能相互作用,这时,就需要提升到公共父组件处理要渲染的数据。
例如:官网 摄氏度和华氏度控制水沸腾的例子
3. 数据流向:
状态管理组件(父组件) 通过 【属性绑定】 状态 和 改变状态的方法
子组件通过 props 获取数据和父组件的方法,通过 this.props 渲染数据,调用方法。
/*数据处理的公共方法*/ function toCelsius(fahrenheit) { return (fahrenheit - 32) * 5 / 9; } function toFahrenheit(celsius) { return (celsius * 9 / 5) + 32; } function tryConvert(temperature, convert) { const input = parseFloat(temperature); if (Number.isNaN(input)) { return ''; } const output = convert(input); const rounded = Math.round(output * 1000) / 1000; return rounded.toString(); } const scaleNames = { c: 'Celsius', f: 'Fahrenheit' }; // 1. 抽离温度显示组件 class TemperatureInput extends React.Component{ constructor (props) { super(props) this.handleChangeT = this.handleChangeT.bind(this) this.inputRef = React.createRef() } // 通过事件触发父组件的方法 handleChangeT (e) { console.log(this.inputRef) // 通过props触发父组件的方法 this.props.onTemperatureChange(this.inputRef.current.value) } render () { const temperature = this.props.temperature return ( <fieldset> {this.props.type === 'c' ? <legend>请输入摄氏度</legend> : <legend>请输入华氏度</legend>} <input value={temperature} onChange={this.handleChangeT} ref={this.inputRef} /> </fieldset> ) } } // 抽取 Calculator 组件, 管理状态 class Calculator extends React.Component { constructor (props) { super(props) this.state = { temperature: '', type: 'c' } this.calcC = this.calcC.bind(this) this.calcF = this.calcF.bind(this) } calcC (temperature) { this.setState({ temperature, type: 'c' }) } calcF (temperature) { this.setState({ temperature, type: 'f' }) } render() { // 计算摄氏度,华氏度 fahrenheit const temperature = this.state.temperature const fahrenheit = this.state.type === 'c' ? tryConvert(temperature, toFahrenheit) : temperature const celsius = this.state.type === 'f' ? tryConvert(temperature, toCelsius) : temperature return (
// onTemperatureChange属性传递方法给子组件 <div> <TemperatureInput type="c" onTemperatureChange={this.calcC} temperature={celsius} /> <TemperatureInput type="f" onTemperatureChange={this.calcF} temperature={fahrenheit} /> {celsius >= 100 ? <h2>水沸腾了</h2> : <h2>水还没开</h2>} </div> ) } } ReactDOM.render( <Calculator />, document.getElementById('root') )