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') )

 

posted @ 2020-06-08 15:59  monkey-K  阅读(281)  评论(0编辑  收藏  举报