本文由云+社区发表

作者:前端林子

1.七个可选的生命周期

可以结合下图来看:

(1) componentWillMount() 仅在render()方法前被调用一次,如果在该方法中调用了setState方法去改变组件的状态值,那么调用render()后,将会直接看到改变过了的状态值,并且不论状态值怎么改变,componentWillMount()都不会再被调用。

(2) componentDidMount() 仅在render()方法后被立即调用一次(客户端),相对于父组件而言,该方法在子组件中会先被调用。如果需要使用一些JaveScript框架或者类似于setInterval()这样的方法,建议在该方法内使用。

(3) ShouldComponentUpdate(object nextProps, object nextState) 在初始渲染调用render()方法时不会被调用,后面在接受到新的state或者props时,在render()方法前被调用。为防止一些潜在的bug,该方法默认总是返回true。如果你确定state及props改变后不需要渲染组件,那么也可以指定返回false,需要注意的是,这样的结果会导致后面的render()、componentWillUpdate()、componentDidUpdate()都不会被调用。

一般的,我们可以通过该函数来优化性能:

一个React项目需要更新一个小组件时,很可能需要父组件更新自己的状态。而一个父组件的重新更新会造成它旗下所有的子组件重新执行render()方法,形成新的虚拟DOM,再用diff算法对新旧虚拟DOM进行结构和属性的比较,决定组件是否需要重新渲染

无疑这样的操作会造成很多的性能浪费,所以我们开发者可以根据项目的业务逻辑,在shouldComponentUpdate()中加入条件判断,从而优化性能

例如React中的就提供了一个PureComponent的类,当我们的组件继承于它时,组件更新时就会默认先比较新旧属性和状态,从而决定组件是否更新。值得注意的是,PureComponent进行的是浅比较,所以组件状态或属性改变时,都需要返回一个新的对象或数组

(4) componentWillReceiveProps(object nextProps) 在初始渲染调用render()方法时不会被调用,当接收到一个新的props时,该方法被调用。我们都知道,如果改变一个状态的值,则会触发render()方法,所以可以在这个方法里调用setState()方法去改变一个状态的值,当该方法接收到新的props时,setState()就可以避免一次额外的render()了。 在这个方法里,尤其需要注意一点,就是接收到新的props一定会触发render()方法,但是render()方法被触发不一定是因为接收到了新的props

(5) componentWillUpdate(object nextProps, object nextState) 在初始渲染调用render()方法时不会被调用,当接收到新的props及state时,在render()方法之前被调用。

不要在此方法再去更新props 或者 state

(6) componentDidUpdate(object prevProps, object prevState) 在初始渲染调用render()方法时不会被调用,当组件更新被刷新到DOM之后被立即调用。

可以在这里访问,并修改 DOM

(7) componentWillUnmount() 在组件从DOM上卸载前被调用,在这个方法里面,我们主要是完成一些清除操作,比如说清除掉一些过时了的定时器等。

2.执行顺序及次数

(1) getDefaultProps(),调用1次

(2) getInitialState(),调用1次

(3) componentWillMount(),调用1次

(4) render(),调用>=1次

(5) componentDidMount():仅客户端,调用1次

(6) componentWillReceiveProps(object nextProps),调用>=0次

(7) ShouldComponentUpdate(object nextProps, object nextState),调用>=0次

(8) componentWillUpdate(object nextProps, object nextState),调用>=0次

(9) render(),调用>=1次

(10) componentDidUpdate(object prevProps, object prevState),调用>=0次

(11) componentWillUnmount(),调用1次

3.实例

我写了一个小demo可直接在浏览器里运行,大家可以通过控制台查看父组件、子组件中的各生命周期调用的顺序:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="https://fb.me/react-15.2.0.js"></script>
  5. <script src="https://fb.me/react-dom-15.2.0.js"></script>
  6. <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
  7. </head>
  8. <body>
  9. <div id="app-container"></div>
  10. <script type="text/babel">
  11. var SubCounter = React.createClass({
  12. componentWillReceiveProps:function() {
  13. console.log('9、子组件将要接收到新属性');
  14. },
  15. shouldComponentUpdate:function(newProps, newState) {
  16. console.log('10、子组件是否需要更新');
  17. if (newProps.number < 5) return true;
  18. return false
  19. },
  20. componentWillUpdate:function() {
  21. console.log('11、子组件将要更新');
  22. },
  23. componentDidUpdate:function() {
  24. console.log('13、子组件更新完成');
  25. },
  26. componentWillUnmount:function() {
  27. console.log('14、子组件将卸载');
  28. },
  29. render:function() {
  30. console.log('12、子组件挂载中');
  31. return (
  32. <p>{this.props.number}</p>
  33. )
  34. }
  35. });
  36. var Counter = React.createClass({
  37. getInitialState:function(){
  38. return(
  39. this.state={
  40. number:0
  41. }
  42. )
  43. },
  44. componentWillMount:function(){
  45. console.log('3、父组件挂载之前');
  46. },
  47. componentDidMount:function(){
  48. console.log('5、父组件挂载完成');
  49. },
  50. shouldComponentUpdate:function(newProps, newState) {
  51. console.log('6、父组件是否需要更新');
  52. if (newState.number<15) return true;
  53. return false
  54. },
  55. componentWillUpdate:function() {
  56. console.log('7、父组件将要更新');
  57. },
  58. componentDidUpdate:function() {
  59. console.log('8、父组件更新完成');
  60. },
  61. handleClick : function(){
  62. this.setState({
  63. number: this.state.number + 1
  64. })
  65. },
  66. render:function() {
  67. console.log('4、render(父组件挂载)');
  68. return (
  69. <div>
  70. <p>{this.state.number}</p>
  71. <button onClick={this.handleClick}>+</button>
  72. {this.state.number<10?<SubCounter number={this.state.number}/>:null}
  73. </div>
  74. )
  75. }
  76. });
  77. ReactDOM.render(<Counter />, document.getElementById('app-container'));
  78. </script>
  79. </body>
  80. </html>

点击一次按钮,通过控制台可以看到:

4.小结

本文主要是图文结合地介绍了react的生命周期及执行顺序,同时附上了一个实例,可以清楚地看到父组件、子组件的调用顺序。如存在问题,欢迎指正~~~

此文已由腾讯云+社区在各渠道发布

获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号

附实例!图解React的生命周期及执行顺序的更多相关文章

  1. Spring的Bean的生命周期方法执行顺序测试

    通过一个简单的Maven工程来演示Spring的Bean生命周期函数的执行顺序. 下面是工程的目录结构: 直接贴代码: pom.xml文件内容: <?xml version="1.0& ...

  2. Unity脚本生命周期与执行顺序

    文章目录 脚本生命周期 MonoBehavior生命周期图 脚本执行顺序 自定义执行顺序 在Unity中,脚本可以理解为附加在游戏对象上的用于定义游戏对象行为的指令代码.必须绑定在游戏对象上才能开始它 ...

  3. react教程 — 组件的生命周期 和 执行顺序

    一.组件执行的生命周期:                  参考  https://www.cnblogs.com/soyxiaobi/p/9559117.html  或  https://www.c ...

  4. MonoBehaviour Lifecycle(生命周期/脚本执行顺序)

    脚本执行顺序 前言 搭建一个示例来验证Unity脚本的执行顺序,大概测试以下部分: 物理方面(Physics) 渲染(Scene rendering) 输入事件(InputEvent) 流程图 Uni ...

  5. Unity3D脚本的生命周期(执行顺序)

    Unity脚本中有许多固定的函数 例如Start();Update(); 而这些函数都有固定的执行顺序 搞清楚这些函数的执行顺序 对于我们理清代码的逻辑就显得尤为重要 举个简单的例子 //脚本A pu ...

  6. vue中的父组件及子组件生命周期的执行顺序

    一.没有任何任何显示与隐藏限制条件的情况下: 1.运行的顺序依次是: 父组件created→父组件beforeMounted→子组件created→子组件beforeMounted→子组件mounte ...

  7. 简单记录一下vue生命周期及 父组件和子组件生命周期钩子执行顺序

    首先,vue生命周期可以用下图来简单理解 当然这也是官方文档的图片,详细的vue周期详解请参考这里 然而当同时存在父子组件的时候生命周期钩子是如何执行的呢? 请看下文: 加载渲染过程父beforeCr ...

  8. React组件生命周期-正确执行运行阶段的函数

    一. 二. <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=" ...

  9. React组件生命周期-正确执行初始化阶段的函数

    一. 二.代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=&quo ...

随机推荐

  1. Python 3.5 filter

    filter(F, L) F: 函数.L:范围 filter的功能是:用函数F把L范围内的参数做过滤 通常和list一起使用,把过滤后的参数做成列表 list(filter(lambda n:not ...

  2. Javascript 标识符及同名标识符的优先级

    一.定义 标识符(Identifier)就是一个名字,用来对变量.函数.属性.参数进行命名,或者用做某些循环语句中的跳转位置的标记. //变量 var Identifier = 123; //属性 ( ...

  3. js函数柯里化,实现bind

    1.柯里化: 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 举个栗子: 一个计算两数之和的函数,需要传递两个参数,柯里化 ...

  4. iOS 开发中keyChain的使用

    我们开发中很多数据都是直接存储到本地沙盒中的,这样当应用程序被卸载后,本地的数据都会被删除.如果我们不想让数据在卸载程序的时候丢失,我们可以用KeyChain来存储我们想要的数据.苹果提供了原生的一套 ...

  5. Codeforces Round #555 (Div. 3) AB

    A:    http://codeforces.com/contest/1157/problem/A 题意:每次加到10的整数倍之后,去掉后面的0,问最多有多少种可能. #include <io ...

  6. 反调试——jmp到那个地址

    目录 1.前言 2.原理讲解 3.代码实现 前言 这节的反调试是通过构造代码来干扰正常的分析.反调试参考CrypMic勒索病毒 原理讲解 在逆向分析汇编代码时,一般都是通过汇编指令call或jmp跳到 ...

  7. [Codeforces Round #516][Codeforces 1063B/1064D. Labyrinth]

    题目链接:1063B - Labyrinth/1064D - Labyrinth 题目大意:给定一个\(n\times m\)的图,有若干个点不能走,上下走无限制,向左和向右走的次数分别被限制为\(x ...

  8. C# 使用WinApi操作剪切板Clipboard

    前言: 最近正好写一个程序,需要操作剪切板 功能很简单,只需要从剪切板内读取字符串,然后清空剪切板,然后再把字符串导入剪切板 我想当然的使用我最拿手的C#来完成这项工作,原因无他,因为.Net框架封装 ...

  9. MVC Web.Config 配置错误

    配置一个MVC项目的 SessionState,查阅了大量的资料,发现都是直接在web.config中直接加入类似的语句就可以了 <sessionState timeout="60&q ...

  10. PHP 5.x和PHP 7 Closure不同行为问题

    同样一段闭包代码,PHP 7 ok的,PHP 5.5.11(Windows 开发机器)上却报错,以为是PHP 5 bug,原来是用法不对,记录一下~ 原代码(自己写的框架的路由部分)最初是这样写的: ...