目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理。本系列文章希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然。
对于 React,其组件生命周期(Component Lifecycle)是它的核心概念,本文从源码入手,来剖析 React 生命周期的管理艺术。
- 阅读本文需要对 React 有一定的了解,如果你不知何为组件的生命周期,请详读 React 生命周期的文档。
- 如果你对 React 组件的生命周期存在些许疑惑,如生命周期如何顺序管理;setState 如何实现异步操作,又是何时真正更新等,那么本文值得阅读。
前言
React 的主要思想是通过构建可复用组件来构建用户界面。所谓组件其实就是 有限状态机,通过状态渲染对应的界面,且每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段进行改变和执行。
有限状态机(FSM),表示有限个状态以及在这些状态之间的转移和动作等行为的模型。一般通过状态、事件、转换和动作来描述有限状态机,下面是描述组合锁状态机的模型图,包括5个状态、5个状态自转换、6个状态间转换和1个复位 RESET 转换到状态 S1。状态机,能够记住目前所处的状态,根据当前的状态可以做出相应的决策,并且在进入不同的状态时,可以做不同的操作。通过状态机将复杂的关系简单化,利用这种自然而直观的方式可以让代码更容易理解。
React 正是利用这一概念,通过管理状态来实现对组件的管理。例如,某个组件有显示和隐藏两个状态,通常会设计两个方法 show() 和 hide() 来实现切换;而 React 只需要设置状态 setState({ showed: true/false }) 即可实现。同时,React 还引入了组件的生命周期概念。通过它就可以实现组件的状态机控制,从而达到 “生命周期-状态-组件” 的和谐画面。
虽然组件、状态机、生命周期这三者都不是 React 独创,如果熟悉 Web Components 标准,它与其中的自定义组件的生命周期的概念相似。但就目前而言,React 是将这三种概念结合地相对清晰流畅的界面库。
初探 React 生命周期
在自定义 React 组件时,根据需要会在组件生命周期的不同阶段实现不同的逻辑。为了查看 组件生命周期的执行顺序,你可以使用 react-lifecycle mixin,将此 mixin 添加到需要观察的组件中,当任何生命周期方法被调用时,都能在控制台观察到对应的生命周期的调用时状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// react-lifecycle mixin import React from 'react'; import ReactDom from 'react-dom'; import LifeCycle from 'react-lifecycle'; const body = document.body; const MyComponent = React.createClass({ mixins: [LifeCycle], render() { console.log('render'); return null; } }); ReactDom.render(<MyComponent />, body); ReactDom.unmountComponentAtNode(body); ReactDom.render(<MyComponent />, body); ReactDom.render(<MyComponent />, body); |
通过反复试验,得到了组件的生命周期在不同状态下的执行顺序:
- 当首次装载组件时,按顺序执行 getDefaultProps、getInitialState、componentWillMount、render 和 componentDidMount;
- 当卸载组件时,执行 componentWillUnmount;
- 当重新装载组件时,此时按顺序执行 getInitialState、componentWillMount、render 和 componentDidMount,但并不执行 getDefaultProps;
- 当再次渲染组件时,组件接受到更新状态,此时按顺序执行 componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render 和 componentDidUpdate。
疑问
- 为何 React 会按上述顺序执行生命周期?
- 为何 React 多次 render 时,会执行生命周期的不同阶段?
- 为何 getDefaultProps 只执行了1次?
详解 React 生命周期
自定义组件(ReactCompositeComponent)的生命周期主要通过三种状态进行管理:MOUNTING、RECEIVE_PROPS、UNMOUNTING,它们负责通知组件当前所处的状态,应该执行生命周期中的哪个步骤,是否可以更新 state。三个状态对应三种方法,分别为:mountComponent、updateComponent、unmountComponent,每个方法都提供了两种处理方法,will 方法在进入状态之前调用,did 方法在进入状态之后调用,三种状态三种方法五种处理方法,此外还提供两种特殊状态的处理方法。
- mountComponent -> MOUNTING
- updateComponent -> RECEIVE_PROPS
- unmountComponent -> UNMOUNTING
createClass 创建自定义组件
createClass 创建自定义组件的入口方法,负责管理生命周期中的 getDefaultProps。getDefaultProps 方法只执行一次,这样所有实例初始化的 props 将会被共享。
通过 createClass 创建自定义组件,利用原型继承 ReactCompositeComponentBase 父类,按顺序合并 mixins,设置初始化 defaultProps,创建元素 ReactElement。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// ReactCompositeComponent 的基类 var ReactCompositeComponentBase = function() {}; // 将 Mixin 合并到 ReactCompositeComponentBase 的原型上 assign( ReactCompositeComponentBase.prototype, ReactComponent.Mixin, ReactOwner.Mixin, ReactPropTransferer.Mixin, ReactCompositeComponentMixin ); var ReactCompositeComponent = { LifeCycle: CompositeLifeCycle, Base: ReactCompositeComponentBase, // 创建组件 createClass: function(spec) { // 构造函数 var Constructor = function(props, context) { this.props = props; this.context = context; this.state = null; var initialState = this.getInitialState ? this.getInitialState() : null; this.state = initialState; }; // 原型继承父类 Constructor.prototype = new ReactCompositeComponentBase(); Constructor.prototype.constructor = Constructor; // 合并 mixins injectedMixins.forEach( mixSpecIntoComponent.bind(null, Constructor) ); mixSpecIntoComponent(Constructor, spec); // mixins 合并后装载 defaultProps (React整个生命周期中 getDefaultProps 只执行一次) if (Constructor.getDefaultProps) { t">if (Constructor.getDefaultProps) { p>
对于 React,其组件生命周期(Component Lifecycle)是它的核心概念,本文从源码入手,来剖析 React 生命周期的管理艺术。
前言React 的主要思想是通过构建可复用组件来构建用户界面。所谓组件其实就是 有限状态机,通过状态渲染对应的界面,且每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段进行改变和执行。 有限状态机(FSM),表示有限个状态以及在这些状态之间的转移和动作等行为的模型。一般通过状态、事件、转换和动作来描述有限状态机,下面是描述组合锁状态机的模型图,包括5个状态、5个状态自转换、6个状态间转换和1个复位 RESET 转换到状态 S1。状态机,能够记住目前所处的状态,根据当前的状态可以做出相应的决策,并且在进入不同的状态时,可以做不同的操作。通过状态机将复杂的关系简单化,利用这种自然而直观的方式可以让代码更容易理解。 React 正是利用这一概念,通过管理状态来实现对组件的管理。例如,某个组件有显示和隐藏两个状态,通常会设计两个方法 show() 和 hide() 来实现切换;而 React 只需要设置状态 setState({ showed: true/false }) 即可实现。同时,React 还引入了组件的生命周期概念。通过它就可以实现组件的状态机控制,从而达到 “生命周期-状态-组件” 的和谐画面。 虽然组件、状态机、生命周期这三者都不是 React 独创,如果熟悉 Web Components 标准,它与其中的自定义组件的生命周期的概念相似。但就目前而言,React 是将这三种概念结合地相对清晰流畅的界面库。 初探 React 生命周期在自定义 React 组件时,根据需要会在组件生命周期的不同阶段实现不同的逻辑。为了查看 组件生命周期的执行顺序,你可以使用 react-lifecycle mixin,将此 mixin 添加到需要观察的组件中,当任何生命周期方法被调用时,都能在控制台观察到对应的生命周期的调用时状态。
通过反复试验,得到了组件的生命周期在不同状态下的执行顺序:
疑问
详解 React 生命周期自定义组件(ReactCompositeComponent)的生命周期主要通过三种状态进行管理:MOUNTING、RECEIVE_PROPS、UNMOUNTING,它们负责通知组件当前所处的状态,应该执行生命周期中的哪个步骤,是否可以更新 state。三个状态对应三种方法,分别为:mountComponent、updateComponent、unmountComponent,每个方法都提供了两种处理方法,will 方法在进入状态之前调用,did 方法在进入状态之后调用,三种状态三种方法五种处理方法,此外还提供两种特殊状态的处理方法。
createClass 创建自定义组件createClass 创建自定义组件的入口方法,负责管理生命周期中的 getDefaultProps。getDefaultProps 方法只执行一次,这样所有实例初始化的 props 将会被共享。 通过 createClass 创建自定义组件,利用原型继承 ReactCompositeComponentBase 父类,按顺序合并 mixins,设置初始化 defaultProps,创建元素 ReactElement。
|