React生命周期

生命周期是一个抽象的概念,在生命周期的整个过程,分成了很多个阶段:

比如挂载阶段(Mount),组件第一次在DOM树中被渲染的过程;

比如更新过程(Update),组件状态发生变化,重新更新渲染的过程;

比如卸载过程(Unmount),组件从DOM树中被移除的过程;

React内部为了告诉我们当前处于哪些阶段,会对我们组件内部实现的某些函数进行回调,这些函数就是生命周期函数:

  • 比如实现componentDidMount函数:组件已经挂载到DOM上时,就会回调;
  • 比如实现componentDidUpdate函数:组件已经发生了更新时,就会回调;
  • 比如实现componentWillUnmount函数:组件即将被移除时,就会回调;

因此我们可以在这些回调函数中编写自己的逻辑代码,来完成自己的需求功能;

1、常用生命周期

在这里插入图片描述

1.1 挂载阶段

1、在挂载阶段,即创建组件实例的时候会先执行组件的constructor方法

  • 如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数

constructor中通常只做两件事情:

1、通过给 this.state 赋值对象来初始化内部的state
2、为事件绑定实例(this)

2、紧接着会执行组件的render方法
3、最后会执行 componentDidMount 方法, 该方法会在组件挂载后(插入 DOM 树中)立即调用

  • 依赖于DOM的操作可以在这里进行
  • 此处是发送网络请求最好的地方(官方建议)
  • 可以在此处添加一些订阅(会在componentWillUnmount取消订阅)

Hello.jsx

import React from 'react';

export default class Hello extends React.Component{
  constructor() {
    super()
    console.log('hello constructor')
  }
  render() {
    console.log('hello render')
    return (
      <h1>hello</h1>
    )
  }
}

App.jsx

import React from 'react'
import Hello from './Hello'

export default class App extends React.Component {
  render() {
    return (
      <div>
        <Hello />
        <Hello />
      </div>
    )
  }
}

在这里插入图片描述
可见如果使用多次组件实例,该组件每次挂载时都会先执行constructor方法再执行render方法
如果在class组件中定义了componentDidMount函数,那么当组件挂载完毕后会被回调:

import React from 'react';

export default class Hello extends React.Component{
  constructor() {
    super()
    console.log('hello constructor')
  }
  render() {
    console.log('hello render')
    return (
      <h1>hello</h1>
    )
  }
  componentDidMount() {
    console.log('componentDidMount...')
  }
}

在这里插入图片描述

1.2 更新阶段

一旦执行了this.setState方法就会触发组件的更新:

  1. 此时会立即执行组件的render方法
  2. 在组件更新完后componentDidUpdate会被立即调用
import React from 'react';

export default class Hello extends React.Component{
  constructor() {
    super()
    this.state = {
      message: 'hello world'
    }
    console.log('hello constructor')
  }
  changeText() {
    this.setState({ message: 'hello react'})
  }
  render() {
    console.log('hello render')
    const {message} = this.state
    return (
      <div>
        <h1>{message}</h1>
        <button onClick={() => this.changeText()}>修改</button>
      </div>
    )
  }
  componentDidMount() {
    console.log('componentDidMount...')
  }
  componentDidUpdate() {
    console.log('componentDidUpdate...')
  }
}

在这里插入图片描述

1.3 卸载阶段

componentWillUnmount 方法会在组件卸载及销毁之前直接调用 :

  • 在此方法中执行必要的清理操作
  • 例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等

Hello.jsx

import React from 'react';

export default class Hello extends React.Component{
  constructor() {
    super()
    this.state = {
      message: 'hello world'
    }
    console.log('hello constructor')
  }
  render() {
    console.log('hello render')
    const {message} = this.state
    return (
      <div>
        <h1>{message}</h1>
      </div>
    )
  }
  componentDidMount() {
    console.log('componentDidMount...')
  }
  componentWillUnmount() {
    console.log('componentWillUnmount...')
  }
}

App.jsx

import React from 'react'
import Hello from './Hello'

export default class App extends React.Component {
  constructor() {
    super()
    this.state = {
      isShow: true
    }
  }
  changeShow() {
    this.setState({ isShow: !this.state.isShow})
  }
  render() {
    return (
      <div>
        <button onClick={() => this.changeShow()}>切换</button>
        { this.state.isShow && <Hello />}
      </div>
    )
  }
}

在这里插入图片描述

2、不常用生命周期

在这里插入图片描述

2.1 挂载阶段

在挂载阶段,执行完毕constructor后还会执行 static getDerivedStateFromProps() 方法,执行顺序依次为:

  1. constructor()
  2. static getDerivedStateFromProps()
  3. render()
  4. componentDidMount()

static getDerivedStateFromProps(props, state)

该方法使用场景比较罕见,如果state的值在任何时候都依赖于props时才使用此方法

  • 该方法会在render前被调用,并且在初始挂载及后续更新时都会被调用
  • 该方法会返回一个对象来更新state,如果返回null则不更新任何内容
  • 该方法的存在只有一个目的:让组件在props变化时来更新state

2.2 更新阶段

在更新阶段会依次执行:

  1. static getDerivedStateFromProps()
  2. shouldComponentUpdate()
  3. render()
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate()

shouldComponentUpdate(nextProps, nextState)

当props或state发生变化时,该方法会在渲染之前被调用,返回值默认是true,如果返回false则不重新渲染组件。

  • 该方法常用于性能优化,不要企图依靠此方法来阻止渲染,因为这可能会产生bug
  • 如果返回了false则不会执行rendercomponentDidUpdate

App.jsx

import React from "react"
import HelloWorld from "./HelloWorld"

class App extends React.Component {

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

export default App

HelloWord.jsx

import React from "react"

class HelloWorld extends React.Component {
  constructor() {
    console.log("constructor...")
    super()

    this.state = {
      message: "Hello World"
    }
  }

  changeText() {
    this.setState({ message: "Hello React" })
  }

  render() {
    console.log("render...")
    const { message } = this.state

    return (
      <div>
        <h2>{message}</h2>
        <button onClick={e => this.changeText()}>修改文本</button>
      </div>
    )
  }

  componentDidMount() {
    console.log("componentDidMount...")
  }

  componentDidUpdate() {
    console.log("componentDidUpdate...")
  }

  shouldComponentUpdate() {
    return true
  }
}

export default HelloWorld

如果 shouldComponentUpdate()返回了true,在点击按钮修改文本时:
在这里插入图片描述
如果 shouldComponentUpdate()返回了false,在点击按钮修改文本时:

 shouldComponentUpdate() {
    return false
  }

在这里插入图片描述

getSnapshotBeforeUpdate(prevProps, prevState)

该方法会在componentDidUpdate之前被调用,可以用来在组件发生变更前从DOM中捕获一些信息(如滚动位置)。

  • 该方法返回的内容会作为参数传递给componentDidUpdate
import React from "react"

class HelloWorld extends React.Component {
  constructor() {
    console.log("constructor...")
    super()

    this.state = {
      message: "Hello World"
    }
  }

  changeText() {
    this.setState({ message: "Hello React" })
  }

  render() {
    console.log("render...")
    const { message } = this.state

    return (
      <div>
        <h2>{message}</h2>
        <button onClick={e => this.changeText()}>修改文本</button>
      </div>
    )
  }

  componentDidMount() {
    console.log("componentDidMount...")
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("componentDidUpdate...", prevProps, prevState, snapshot)
  }

  getSnapshotBeforeUpdate() {
    console.log('getSnapshotBeforeUpdate...')
    return {
      scrollTop: 100
    }
  }
}

export default HelloWorld

在这里插入图片描述

3、对比老版生命周期

3.1 react生命周期(旧)

在这里插入图片描述

3.2 react生命周期(新)

在这里插入图片描述

3.3 对比

通过两个图的对比,可以发现新版的生命周期减少了以下三种方法:

  1. componentWillMount
  2. componentWillReceiveProps
  3. componentWillUpdate

其实这三个方法仍然存在,只是在前者加上了UNSAFE_前缀,如UNSAFE_componentWillMount,并不像字面意思那样表示不安全,而是表示这些生命周期的代码可能在未来的 react版本可能废除

同时也新增了两个生命周期函数:

  1. getDerivedStateFromProps
  2. getSnapshotBeforeUpdate

上文已有介绍

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值