React@17.0.2生命周期

一、React生命周期(初始化)

1.1 初始化阶段

1、componentWillMountrender之前最后一次修改状态的机会
(注意:将被弃用,不被推荐使用。如果有需求,官方推荐在constructor中去做或者改成UNSAFE_componentWillMount)(为什么被弃用?在react16.2之后发生了改变,推出了新的生命周期,旧的生命周期将被弃用,)
2、render:只能访问this.propsthis.state ,不允许修改状态和DOM输出
3、componentDidMount:成功render并渲染完成真实DOM之后触发,可以修改DOM(初始化,执行一次)

1.2 示例

新建Lifecycle.js组件,写入如下代码:

import React, { Component } from 'react'

export default class Lifecycle extends Component {

  state = {
      text: 'react'
  }

  componentWillMount() {
      console.log("will mount", this.state.text, document.getElementById('text'))

      // 第一次上树前的 最后一次修改状态
      this.setState({
          text: "React"
      })
  }  
  componentDidMount() {
    console.log("did mount", document.getElementById('text'))

    // 数据axios数据请求
    // 订阅函数调用
    // setInterval
    // 基于创建完的dom进行初始化
  }
 
  render() {
      console.log('render')
    return (
      <div >
          <span id="text">{this.state.text} Life cycle</span></div>
    )
  }
}

可以看到效果:
在这里插入图片描述

二、React生命周期(运行中)

2.1 运行中阶段

1、componentWillReceiveProps:父组件修改属性触发
2、shouldComponentUpdate:返回false会阻止render调用(每次改变setState都会执行componentWillUpdaterendercomponentDidUpdate。利用shouldComponentUpdate判断state的值是否改变,没有改变的话就return false;)
3、componentWillUpdate:不能修改属性和状态(注意:将被弃用,不被推荐使用。如果有需求,或者改成UNSAFE_componentWillUpdate)(为什么被弃用?在react16.2之后发生了改变,推出了新的生命周期,旧的生命周期将被启用,)
4、render:只能访问this.propsthis.state,不允许修改状态和DOM输出
5、componentDidUpdate:可以修改DOM(在componentDidUpdate有两个参数,prevProps,preState,可以在componentDidUpdate判断prevProps)

2.2 示例

新建service.js组件,写入:

import React, { Component } from 'react'

export default class Service extends Component {
  state = {
      name: 'react'
  }  
  render() {
      console.log('render')
    return (
      <div>
          <button onClick={() => {
              this.setState({
                  name: 'React'
              })
          }}>click</button>
          {this.state.name}
      </div>
    )
  }

 shouldComponentUpdate(nextProps,nextState) {
    //   nextProps 老状态
    //   nextState 新状态
      if (JSON.stringify(this.state) !== JSON.stringify(nextState)) {
        return true;
      }
      return false; 
  }
  componentWillUpdate() {
    console.log("componentWillUpdate")
  }

  componentDidUpdate() {
    console.log("componentDidUpdate")
// 更新后,要获取dom节点
  }
}

效果:
在这里插入图片描述


2.3 shouldComponentUpdate性能优化示例

新建scu.js组件,写入代码:

import React, { Component } from 'react'

class Child extends Component {

    // 现在是全部子组件都会diff算法
    // 在scu生命组件中 优化 比对即将更改的子组件
    shouldComponentUpdate(nextProps) {
        if (this.props.index === this.props.active || nextProps.index === nextProps.active) {
            console.log(this.props.index, this.props.active, nextProps.index, nextProps.active)
            return true
        }
        return false
     }

    render() {
        console.log('Child render')
        return (
            <div style={{ 
                width: '200px', 
                height: '200px', 
                border: '3px solid', 
                float: 'left', marginLeft: '20px', marginBottom: '20px',
                borderColor: this.props.index === this.props.active ? 'red' : 'gray'}}>
            </div>
        )
    }
}

export default class Scu extends Component {

    state = {
        list: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
        active: '0'
    }

    render() {
        return (
            <div>
                <input style={{ marginBottom: '20px' }} onChange={(event) => {
                    this.setState({
                        active: event.target.value
                    })
                }}></input>
                <div style={{ overflow: 'hidden' }}>
                    {this.state.list.map((item, index) => {
                        return <Child index={String(index)} active={this.state.active} key={index}>{item}</Child>
                    })}
                </div>
            </div>
        )
    }
}

效果:
在这里插入图片描述
可以看到只更新两次。


2.4 componentWillReceiveProps示例

创建ReceiveProps.js组件写入代码:

import React, { Component } from 'react'

class Child extends Component {

    componentWillReceiveProps() {
        console.log('componentWillReceiveProps')
    }

    render() {
        return (
            <div>
                Child
            </div>
        )
    }
}

export default class ReceiveProps extends Component {
  
  state = {
      text: 'react'
  }

  render() {
    return (
      <div>
          {
              this.state.text
          }
          <button onClick={() => {
              this.setState({
                  text: 'React'
              })
          }}>
              click
          </button>
          <Child></Child>
      </div>
    )
  }
}

效果:
在这里插入图片描述
可以看到父组件更新,子组件的生命周期componentWillReceiveProps也被触发了,所以这样子是会影响性能。

三、React生命周期(销毁)

3.1 销毁阶段

componentWillUnmount:在删除组件之前进行清理操作,比如计时器和事件监听器解绑。

3.2 示例

新建componentWillUnmount.js组件,写入代码:

import React, { Component } from 'react'

export default class ComponentWillUnmount extends Component {
  
  state = {
      flag: true
  }

  render() {
    return (
      <div>
          <button onClick={() => {
              this.setState({
                  flag: !this.state.flag
              })
          }}>click</button>
          {this.state.flag && <Child></Child>}
      </div>
    )
  }
}

class Child extends Component {

    
    componentDidMount() {
        this.timer =  setInterval(() => {
            console.log(888)
        }, 1000)
    }

    render () {
        return (
            <div>子组件</div>
        )
    }
    
    componentWillUnmount() {
        clearInterval(this.timer)
    }
}

效果:
在这里插入图片描述
可以看到子组件存在时计时器一直在运行,当我们将子组件销毁时,我们需求将此计时器清空,可以看到我们在销毁组件钩子函数中,进行了该操作。


四、React新生命周期

4.1 老生命周期问题

1、componentWillMount,在ssr中这个方法将会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄露,变得不够安全高效逐步废弃。
2、componentWillReceiveProps外部组件多次频繁更新传入多次不同的props,会导致不必要的异步请求
3、componentWillUpdate,更新前记录DOM状态,可能会做一些处理,与componentDidUpdate相隔时间如果过长,会导致状态不太行

4.2 getDerivedStateFromProps

getDerivedStateFromProps第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子),返回null则说明不需要在这里更新state。(取代componentWillMountcomponentWillReceiveProps

新建getDerivedStateFromProps.js组件,写入代码:

import React, { Component } from 'react'

export default class GetDerivedStateFromProps extends Component {

    state = {
        name: 'react'
    }

    // 初始化执行  状态改变也会执行
    static getDerivedStateFromProps(nextProps, nextState) {

        console.log('GetDerivedStateFromProps')
        return {
            name: nextState.name.substring(0,1).toUpperCase() + 
            nextState.name.substring(1)
        }
    }

    render() {
        return (
            <div>
                <button onClick={() => {
                    this.setState({
                        name: 'hello react GetDerivedStateFromProps'
                    })
                }}>click</button>
                <div>{this.state.name}</div>
            </div>
        )
    }
}

效果:
在这里插入图片描述
在这里插入图片描述

4.3 getSnapshotBeforeUpdate

getSnapshotBeforeUpdate取代了componentWillUpdate,触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数。

新建getSnapshotBeforeUpdate.js组件,写入代码:

import React, { Component } from 'react'

export default class GetSnapshotBeforeUpdate extends Component {

  myref = React.createRef()

  state = {
      list: [1,2,3,4,5,6,7,8,9,10]
  }

  getSnapshotBeforeUpdate() {
      console.log(this.myref.current.scrollHeight)
      // 获取容器高度
    return this.myref.current.scrollHeight
  }
    
  componentDidUpdate(prevProps, prevState, value) {
      console.log(this.myref.current.scrollHeight)
      this.myref.current.scrollTop += this.myref.current.scrollHeight - value
  }

  render() {
    return (
      <div>
          <button onClick={() => {
              this.setState({
                  list: [...[11,12,13,14,15,16,17,18],...this.state.list]
              })
          }}>来消息</button>
          <h1>消息通知</h1>
          <div style={{height: "200px", overflow: "auto"}} ref={this.myref}>
              <ul>
                  {
                      this.state.list.map((item, index) => 
                          <li key={index} style={{height: "100px", backgroundColor: 'yellow'}}>{item}</li>
                      )
                  }
              </ul>
          </div>
      </div>
    )
  }
}

效果:
在这里插入图片描述

五、react生命周期性能优化

1、shouldComponentUpdate
控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下,需要进行优化。
2、PureComponent(在extends时不要继承Component,而是继承PureComponent)
PureComponent会帮你比较新props和旧props,新的state和老的state(值相等,或者对象含有相同的属性,且属性值相等),决定shouldcomponentUpdate返回true或者false,从而决定要不要呼叫render 。(如果state和props永远都在变,那PureComponent并不会比较快,因为shallowEqual也需要花时间)

在学习React的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你华还是你华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值