【React】React组件生命周期以及触发顺序(部分与vue做比较)

这篇具有很好参考价值的文章主要介绍了【React】React组件生命周期以及触发顺序(部分与vue做比较)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在学习React,发现其中的生命周期跟Vue有一些共同点,但也有比较明显的区别,并且执行顺序也值得讨论一下,于是总结了一些资料在这里,作为学习记录。

v17.0.1后生命周期图片

【React】React组件生命周期以及触发顺序(部分与vue做比较),react.js,前端,前端框架

初始化阶段

由ReactDOM.render()触发 —— 初次渲染

  1. constructor() —— 类组件中的构造函数
  2. static getDerivedStateFromProps(props, state) 从props得到一个派生的状态【新增,不常用】
  3. render() —— 挂载组件
  4. componentDidMount() —— 组件挂载完成 比较常用
    总结:
    constructor 对标 Vue中的beforeCreate/created
    componentDidMount 对标 Vue中的 Mounted
    在一个完整的生命周期中,constructor 与 componentDidMount 只会执行一次。
    在一个完整的生命周期中,render会执行多次
    注意:
    在React中,我们在componentDidMount 中发请求,绝对不在constructor 中发请求。

更新阶段

由组件内部this.setSate()或父组件重新render触发或强制更新forceUpdate()

  1. getDerivedStateFromProps() —— 从props得到一个派生的状态 【新增,不常用】
  2. shouldComponentUpdate() —— 组件是否应该被更新(默认返回true)
  3. render() —— 挂载组件
  4. getSnapshotBeforeUpdate() —— 在更新之前获取快照【新增,不常用】
  5. componentDidUpdate(prevProps, prevState, snapshotValue) —— 组件完成更新。
    总结:
    触发组件更新的方式(常用),两种:
    1. 💥props 值的改变
    2. 💥setState() 改变state
      更新阶段触发的钩子函数,有两个
      1. render
      2. componentDidUpdate
        render与componentsDidUpdate 都可以拿到更新后的值。
        render与componentsDidUpdate 中都不能调用setState ,会造成死循环。
        注意:
        不论DOM中有没有使用数据,钩子函数都会被触发。(与vue不同)
        react中的更新,指的是数据更新,而非视图更新。(与vue不同)

卸载组件

由ReactDOM.unmountComponentAtNode()触发

  1. componentWillUnmount() —— 组件即将卸载

重要的勾子

  1. render:初始化渲染或更新渲染调用
  2. componentDidMount:开启监听, 发送ajax请求
  3. componentWillUnmount:做一些收尾工作, 如: 清理定时器

即将废弃的勾子

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

代码案例

效果
【React】React组件生命周期以及触发顺序(部分与vue做比较),react.js,前端,前端框架
代码展示

父组件:Parent.js

import React, { Component } from 'react';
import { Button } from 'antd';
import Child from './child';

const parentStyle = {
  padding: 40,
  margin: 20,
  backgroundColor: 'LightCyan',
};

const NAME = 'Parent 组件:';

export default class Parent extends Component {
  constructor() {
    super();
    console.log(NAME, 'constructor');
    this.state = {
      count: 0,
      mountChild: true,
    };
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    console.log(NAME, 'getDerivedStateFromProps');
    return null;
  }

  componentDidMount() {
    console.log(NAME, 'componentDidMount');
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log(NAME, 'shouldComponentUpdate');
    return true;
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log(NAME, 'getSnapshotBeforeUpdate');
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log(NAME, 'componentDidUpdate');
  }

  componentWillUnmount() {
    console.log(NAME, 'componentWillUnmount');
  }

  /**
   * 修改传给子组件属性 count 的方法
   */
  changeNum = () => {
    let { count } = this.state;
    this.setState({
      count: ++count,
    });
  };

  /**
   * 切换子组件挂载和卸载的方法
   */
  toggleMountChild = () => {
    const { mountChild } = this.state;
    this.setState({
      mountChild: !mountChild,
    });
  };

  render() {
    console.log(NAME, 'render');
    const { count, mountChild } = this.state;
    return (
      <div style={parentStyle}>
        <div>
          <h3>父组件</h3>
          <Button onClick={this.changeNum}>改变传给子组件的属性 count</Button>
          <br />
          <br />
          <Button onClick={this.toggleMountChild}>卸载 / 挂载子组件</Button>
        </div>
        {mountChild ? <Child count={count} /> : null}
      </div>
    );
  }
}

子组件: Child.js

import React, { Component } from 'react';
import { Button } from 'antd';

const childStyle = {
  padding: 20,
  margin: 20,
  backgroundColor: 'LightSkyBlue',
};

const NAME = 'Child 组件:';

export default class Child extends Component {
  constructor() {
    super();
    console.log(NAME, 'constructor');
    this.state = {
      counter: 0,
    };
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    console.log(NAME, 'getDerivedStateFromProps');
    return null;
  }

  componentDidMount() {
    console.log(NAME, 'componentDidMount');
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log(NAME, 'shouldComponentUpdate');
    return true;
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log(NAME, 'getSnapshotBeforeUpdate');
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log(NAME, 'componentDidUpdate');
  }

  componentWillUnmount() {
    console.log(NAME, 'componentWillUnmount');
  }

  changeCounter = () => {
    let { counter } = this.state;
    this.setState({
      counter: ++counter,
    });
  };

  render() {
    console.log(NAME, 'render');
    const { count } = this.props;
    const { counter } = this.state;
    return (
      <div style={childStyle}>
        <h3>子组件</h3>
        <p>父组件传过来的属性 count : {count}</p>
        <p>子组件自身状态 counter : {counter}</p>
        <Button onClick={this.changeCounter}>改变自身状态 counter</Button>
      </div>
    );
  }
}

从五种组件状态改变的时机来探究生命周期的执行顺序

一、父子组件初始化

父子组件第一次进行渲染加载时:
控制台的打印顺序为:

  • Parent 组件: constructor()
  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: render()
  • Child 组件: constructor()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: render()
  • Child 组件: componentDidMount()
  • Parent 组件: componentDidMount()

二、子组件修改自身状态 state

点击子组件 [改变自身状态counter] 按钮,其 [自身状态counter] 值会 +1, 此时控制台的打印顺序为:

  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()

三、修改父组件中传入子组件的 props

点击父组件中的 [改变传给子组件的属性 count] 按钮,则界面上 [父组件传过来的属性 count] 的值会 + 1,控制台的打印顺序为:

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()
  • Parent 组件: componentDidUpdate()

四、卸载子组件

点击父组件中的 [卸载 / 挂载子组件] 按钮,则界面上子组件会消失,控制台的打印顺序为:

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentWillUnmount()
  • Parent 组件: componentDidUpdate()

五、重新挂载子组件

再次点击父组件中的 [卸载 / 挂载子组件] 按钮,则界面上子组件会重新渲染出来,控制台的打印顺序为:文章来源地址https://www.toymoban.com/news/detail-729592.html

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: constructor()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: render()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidMount()
  • Parent 组件: componentDidUpdate()

父子组件生命周期执行顺序总结:

  • 当子组件自身状态改变时,不会对父组件产生副作用的情况下,父组件不会进行更新,即不会触发父组件的生命周期
  • 当父组件中状态发生变化(包括子组件的挂载以及卸载)时,会触发自身对应的生命周期以及子组件的更新
    • render 以及 render 之前的生命周期,则 父组件先执行
    • render之后的生命周期,子组件先执行,并且与父组件交替执行
  • 当子组件进行卸载时,只会执行自身的 componentWillUnmount 生命周期,不会再触发别的生命周期

到了这里,关于【React】React组件生命周期以及触发顺序(部分与vue做比较)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【React学习】React组件生命周期

    在 React 中,组件的生命周期是指组件从被创建到被销毁的整个过程。React框架提供了一系列生命周期方法,在不同的生命周期方法中,开发人员可以执行不同的操作,例如初始化状态、数据加载、渲染、更新等。一个组件的生命周期大致可以分为三个阶段,即组件挂载时,更

    2024年02月12日
    浏览(40)
  • React 组件生命周期

    Mounting(挂载):已插入真实 DOM Updating(更新):正在被重新渲染 Unmounting(卸载):已移出真实 DOM Mounting阶段叫挂载阶段,伴随整个虚拟DOM的声明。它里面有四个小的生命周期函数,分别是: constructor:初始化属性 componentWillMount:在组件即将被挂载到页面的时候执行 render:页面s

    2024年02月10日
    浏览(48)
  • 【React】组件生命周期、组件通信、setState

    ◼ 组件化思想的应用: ​  有了组件化的思想,我们在之后的开发中就要充分的利用它。 ​  尽可能的将页面拆分成一个个小的、可复用的组件。 ​  这样让我们的代码更加方便组织和管理,并且扩展性也更强。 ◼ React的组件相对于Vue更加的灵活和多样,按照不同的

    2024年01月20日
    浏览(43)
  • React之组件的生命周期

    生命周期:一个事务从创建到最后消亡经历的整个过程 组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程 意义:理解组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等 钩子函数的作用:为开发人员在不同

    2024年02月15日
    浏览(36)
  • 面试题-React(六):React组件和生命周期

    一、React组件 React组件简介: React组件是构建用户界面的基本单元。它们将界面拆分成独立、可重用的部分,使得代码更加模块化、可维护性更高。React组件可以是函数组件或类组件,它们接收输入的数据(称为props)并返回表示用户界面的React元素。 创建React组件: 在React中

    2024年02月11日
    浏览(33)
  • uniapp 微信小程序:页面+组件的生命周期顺序

    这个uniapp的微信小程序项目使用的是 VUE2 首页只提供了一个跳转按钮。 虽然文档中将页面与组件的生命周期分开罗列,但是我们在页面和组件中所有的生命周期函数都加上,看下效果: uniap 页面生命周期 uniapp 组件生命周期

    2024年02月15日
    浏览(41)
  • 前端页面点击刷新-触发vue生命周期加载最新数据

    需求背景:layout布局,页面头部通过定时器获取后端消息的伪消息通知功能,在点击消息时获取所有消息总数并且刷新页面,以便触发vue的生命周期重新获取所有消息,消息展示在content中。  要触发页面刷新,可以使用vue路由的router.push方法,添加一个动态的query参数,可以

    2024年02月21日
    浏览(53)
  • 【React】- 组件生命周期连续渲染两次问题

    最近在整理生命周期相关的知识内容,然后发现一个奇怪的现象,即组件的生命周期会运行2次!经过确认不是代码问题,于是开始找度娘,终于找到其原因-React中的严格模式,在这里记录一下 一、问题重现 如图所示,当组件初始化渲染时,每个周期都走了2次,按理说初始化

    2024年02月15日
    浏览(37)
  • 面试中问:React中函数组件和class组件的区别,hooks模拟生命周期

    React 的函数组件和类组件在很多方面都相似,但它们也有一些关键的差异。以下是这两种组件之间的主要区别: 定义方式 : 函数组件 : 是简单的 JavaScript 函数,接受 props 为参数,并返回 React 元素。 类组件 : 是 ES6 的类,继承的时候要用到 extends React.Component,至少包含一个名

    2024年02月11日
    浏览(45)
  • 微信小程序:uni-app页面Page和组件Component生命周期执行的先后顺序

    文档 页面生命周期 https://uniapp.dcloud.net.cn/tutorial/page.html#lifecycle 组件生命周期 https://uniapp.dcloud.net.cn/tutorial/page.html#componentlifecycle 经测试,得出结论: H5和微信小程序的生命周期函数调用顺序不一致 一般情况下,主要使用的周期函数如下,他们的执行顺序是固定的 页面 组件

    2024年02月08日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包