React 生命周期

React生命周期(生命周期钩子函数)

一个关于生命周期的demo

需求:定义组件实现以下功能:

  • 让指定的文本做显示 / 隐藏的渐变动画

  • 从完全可见,到彻底消失,耗时2S

  • 点击按钮从界面上卸载组件


class Demo extends React.Component{
   state = {
       opacity:1
   }
   // 卸载组件
   handleComponent = () => { 
       ReactDOM.unmountComponentAtNode(document.getElementById('test'))
   } 
   // 组件挂载完毕
   componentDidMount(){
       this.timer = setInterval(()=>{
           let {opacity} = this.state;
           opacity -= 0.1
           if (opacity <= 0) opacity = 1 
           this.setState({
               opacity:opacity
           })
       },200)
   } 
   // 组件将要卸载
   componentWillUnmount(){
       clearInterval(this.timer)
   } 
   // 初始化渲染组件,状态更新之后 
   render(){
       console.log("render")
       return (
           <div>
               <h2 style={{opacity:this.state.opacity}}>react的生命周期</h2>
               <button onClick={this.handleComponent}>卸载组件</button>
           </div>
       )
   }
}
// 渲染组件
ReactDOM.render(<Demo />,document.getElementById("test"))

理解

组件从创建到死亡它会经历一些特定的阶段。

React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。

我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

生命周期流程图(旧)

1. 初始化阶段: 由ReactDOM.render()触发---初次渲染

(1)constructor()

constructor()中完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。
注意:只要使用了constructor()就必须写super(),否则会导致this指向错误。

(2)componentWillMount()

它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。

(3)render()

render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

初始化渲染或更新渲染调用

(4)componentDidMount()

组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染。

一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息

2.更新阶段: 由组件内部this.setSate()或父组件重新render触发

  • 1)setSate更新状态 :shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

  • 2)forceUpdate更新(不更改任何状态中的数据,强制更新一下):componentWillUpdate -> render -> componentDidUpdate

  • 3)父组件重新render触发:componentWillReceiveProps -> shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

componentWillReceiveProps (nextProps)

  • 在接受父组件改变后的props需要重新渲染组件时用到的比较多

  • 接受一个参数nextProps

  • 通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件

shouldComponentUpdate(nextProps,nextState)

  • 主要用于性能优化(部分更新)

  • 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新

  • 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断

componentWillUpdate (nextProps,nextState)

shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate

componentDidUpdate(prevProps,prevState)

组件更新完成

3.卸载组件: 由ReactDOM.unmountComponentAtNode()触发

componentWillUnmount()

一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息


class Count extends React.Component { 
  constructor(props){ 
      console.log("Count constructor");
      super(props);  
      // 初始化状态
      this.state = {
          num: 0
      } 
  } 
  // 方法
  add = () => {
      let { num } = this.state; 
      this.setState({
          num: num+1
      })
  } 
  //卸载组件按钮的回调
  death = ()=>{
    ReactDOM.unmountComponentAtNode(document.getElementById('test'))
  } 
  //强制更新按钮的回调
  force = ()=>{
    this.forceUpdate()
  } 
  //组件将要挂载的钩子
  componentWillMount() {
      console.log("Count componentWillMount")
  }  
  // 组件挂载完毕的钩子
  componentDidMount() {
      console.log("Count componentDidMount")
  }  
  //控制组件更新的“阀门”
  shouldComponentUpdate(){
    console.log('Count shouldComponentUpdate');
    return true
  } 
  // 组件将要更新的钩子
  componentWillUpdate(){
      console.log('Count componentWillUpdate');
  } 
  // 组件更新完毕的钩子
  componentDidUpdate() {
      console.log("Count componentDidUpdate")
  }  
  // 初始化渲染组件,状态更新之后 
  render() {
      console.log("Count render")
      return (
          <div>
              <h2>当前求和:{this.state.num}</h2>
              <button onClick={this.add}>点我+1</button>
              <button onClick={this.death}>卸载组件</button>
						<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
          </div>
      )
  }
}
// 渲染组件
ReactDOM.render(<Count />, document.getElementById("test"))


// 父组件render 
class A extends React.Component {
  state = {
      name:"张三"
  }
  changeName = () => {
      this.setState({
          name:"李四"
      })
  }

  render(){
      return (
          <div>
              <h2>A组件</h2>
              <B name={this.state.name}></B>
              <button onClick={this.changeName}>改变名字</button>
          </div>
      )
  }
}
// 子组件
class B extends React.Component { 
  //组件将要接收新的props的钩子
  componentWillReceiveProps(props){
    console.log('B---componentWillReceiveProps',props);
  }
  //控制组件更新的“阀门”
  shouldComponentUpdate(){
    console.log('B---shouldComponentUpdate');
    return true
  }
  //组件将要更新的钩子
  componentWillUpdate(){
    console.log('B---componentWillUpdate');
  }
  //组件更新完毕的钩子
  componentDidUpdate(){
    console.log('B---componentDidUpdate');
  }
  render(){
      console.log('B---render');
      return <h2>B组件:{this.props.name}</h2>
  }
}
ReactDOM.render(<A />, document.getElementById("test1"))

生命周期流程图(新)

1、初始化阶段: 由ReactDOM.render()触发---初次渲染

constructor()

getDerivedStateFromProps()

render()

componentDidMount()

2、更新阶段: 由组件内部this.setSate()或父组件重新render触发

getDerivedStateFromProps

shouldComponentUpdate()

render()

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

componentDidUpdate()

卸载组件: 由ReactDOM.unmountComponentAtNode()触发

componentWillUnmount()

即将废弃的勾子

  • componentWillMount

  • componentWillReceiveProps

  • componentWillUpdate

现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

posted @ 2021-03-11 09:31  流年瓦解我们的记忆  阅读(98)  评论(0编辑  收藏  举报