资讯专栏INFORMATION COLUMN

解读React源码(三):生命周期的管理艺术

lk20150415 / 2877人阅读

摘要:前言的主要思想是通过构建可复用组件来构建页面所谓组件其实就是有限状态机通过状态渲染对应的界面且每个组件都有自己的生命周期它规定了组件的状态和方法需要在哪个阶段改变和执行子组件子组件子组件子组件初探生命周期当首次挂载组件时按顺序执行当卸载组件

前言

React的主要思想是通过构建可复用组件来构建页面.
所谓组件,其实就是有限状态机(FSM),通过状态渲染对应的界面,且每个组件都有自己的生命周期,
它规定了组件的状态和方法需要在哪个阶段改变和执行.

class Collections extends Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 1
        }
    }
    add = () => {
        this.setState({
            a: this.state.a + 1
        });
    }
    componentWillMount() {
        console.log("componentWillMount");
    }
    componentDidMount() {
        console.log("componentDidMount");
        this.setState({
            a: 2
        });
    }
    componentWillUnMount() {
        console.log("componentWillUnMount");
    }
    render() {
        console.log("render");
        return (
            
{ this.state.a }
); } }
import React, { Component, PropTypes } from "react";

export default class Example extends Component {
    static propTypes = {
        a: PropTypes.number.isRequired
    };
    static defaultProps = {
        a: 0
    }; 
    constructor(props) {
        super(props);
        this.state = {
            b: 1
        };
    }
    add = () => {
        this.setState({
            b: this.state.b + 1
        });
    }
    componentWillReceiveProps(nextProps) {
        console.log(nextProps);
        if (nextProps.a === 4) {
            this.setState({
                b: 1000
            });
        }
    }
    shouldComponentUpdate(nextProps, nextState) {
        console.log(nextProps);
        console.log(nextState);
        if (nextState.b === 4) {
            return false;
        }
        return true;
    }
    componentWillMount() {
        console.log("子组件componentWillMount");
    }
    componentDidMount() {
        console.log("子组件componentDidMount");
    }
    render() {
        console.log("子组件render");
        return (
            

a:{ this.props.a }

b:{ this.state.b }

); } }
初探react生命周期

当首次挂载组件时,按顺序执行getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
当卸载组件时,执行componentWillUnMount
当再次渲染组件时,组件接收到更新状态,此时按顺序执行componentWillReceiveProps,shouldComponentUpdate,
componentWillUpdate,render和componentDidUpdate

使用createClass创建自定义组件

createClass是创建自定义组件的入口方法,负责管理生命周期方法中的getDefaultProps.
该方法在整个生命周期中只执行一次,这样所有实例初始化的props将会被共享.
通过createClass创建自定义组件,利用原型继承ReactClassComponent父类,
按顺序合并minin,设置初始化defaultProps,返回构造函数.
当使用ES6 classes编写React组件时,class MyComponent extends React.Component
其实就是调用内部方法createClass创建组件.

var ReactClass = {
    // 创建自定义组件
    createClass: function(spec) {
        var Constructor = function(props, context, updater) {
            // /自动绑定
            if (this._reactAutoBindPairs.length) {
                bindAutoBindMethods(this);
            }

            this.props = props;
            this.context = context;
            this.refs = emptyObject;
            this.updater = updater || ReactNoopUpdateQueue;
            this.state = null;
            // ReactClass没有构造函数,通过getInitialState和componentWillMount来代替
            var initialState = this.getInitialState ? this.getInitialState() : null;
            this.state = initialState;
        };

        // 原型继承父类
        Constructor.prototype = new ReactClassComponent();
        Constructor.prototype.constructor = constructor;
        Constructor.prototype._reactAutoBindPairs = [];

        // 合并mixin
        injectedMixins.forEach(
            minSpecIntoComponent.bind(null, Constructor)
        );

        minSpecIntoComponent(Constructor, spec);

        // 所有mixin合并后初始化defaultProps(在整个生命周期中,getDefaultProps只执行一次)
        if (Constructor.getDefaultProps) {
            Constructor.defaultProps = Constructor.getDefaultProps();
        }
        // 减少查找并设置原型的时间
        for (var methodName in ReactClassInterface) {
            if (!Constructor.prototype[methodName]) {
                Constructor.prototype[methodName] = null;
            }
        }

        return Constructor;
    }
};
MOUNTING

mountComponent负责管理生命周期中的getInitialState,componentWillMount,render和componentDidMount
由于getDefaultProps是通过构造函数进行管理的,所以也是整个生命周期中最先开始执行的.
react是利用更新队列this._pendingStateQueue以及更新状态this._pendingReplaceState
和this._pendingForceUpdate来实现setState的异步更新机制.
其实,mountComponent本质上是通过递归渲染内容的,由于递归的特性,父组件的componentWillMount
在其子组件的componentWillMount之前调用,而父组件的componentDidMount在其子组件的componentDidMount之后调用.

RECEIVE_PROPS

updateComponent负责管理生命周期中的componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,
render和componentDidUpdate.
若存在componentWillReceiveProps,则执行.
如果此时在componentWillReceiveProps中调用setState,是不会触发re-render的,而是会进行state合并.
且在componentWillReceiveProps,shouldComponentUpdate和componentWillUpdate中也还是无法获取到更新后的this.state,
即此时访问的this.state仍然是未更新的数据,因此只有render和componentDidUpdate中才能获取到更新后的this.state

componentWillReceiveProps(nextProps) {
    console.log(nextProps);
    if (nextProps.a === 4) {
        this.setState({
            b: 1000
        }, () => {
            console.log(this.state.b);
        });
    }
}
UNMOUTING

unmountComponnet负责管理生命周期中的componentWillUnMount
如果存在componentWillUnMount,则执行并重置所有相关参数,更新队列以及更新状态,
如果此时在componentWillUpdate中调用setState,是不会触发re-render的,这是因为
所有更新队列和更新状态都被重置为null,并清除了公共类,完成了组件卸载操作.

无状态组件

无状态组件只是一个render方法,并没有组件类的实例化过程,也没有实例返回.
无状态组件没有状态,没有生命周期,只是简单的接受props渲染生成DOM结构,
是一个纯粹为渲染而生的组件.
由于无状态组件有简单,便捷,高效等诸多优点,所以如果可能的话请尽量使用无状态组件.

import React from "react";

const HelloWorld = (props) => {
    return (
        
{ props.a }
); } export default HelloWorld;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84651.html

相关文章

  • 解读React源码(一):初探React源码

    摘要:前言的基本概念组件的构建方法以及高级用法这背后的一切如何运转深入内部的实现机制和原理初探源码代码组织结构包含一系列的工具方法插件包含一系列同构方法包含一些公用或常用方法如等包含一些测试方法等包含一些边界错误的测试用例是代码的核心部分它包含了 前言 React的基本概念,API,组件的构建方法以及高级用法,这背后的一切如何运转,深入Virtual DOM内部的实现机制和原理. 初探Rea...

    Eminjannn 评论0 收藏0
  • React 源码深度解读(七):事务 - Part 1

    摘要:在学习源码的过程中,给我帮助最大的就是这个系列文章,于是决定基于这个系列文章谈一下自己的理解。说明就算抛出了错误,部分的代码也要继续执行,随后再将错误往上层代码抛。和都能保证其中一个成员抛出错误的时候,余下的能继续执行。 前言 React 是一个十分庞大的库,由于要同时考虑 ReactDom 和 ReactNative ,还有服务器渲染等,导致其代码抽象化程度很高,嵌套层级非常深,阅读...

    KavenFan 评论0 收藏0
  • 【Under-the-hood-ReactJS-Part11】React源码解读

    摘要:技术上来说,当方法被调用后或者发生改变后,方法都会被调用。下一步,会设置为。之后,检测当前更新是否由更新引起的。这是因为,使用是导致组件持久化更新,而会被方法的返回值重新赋值。 接上文, React流程图:https://bogdan-lyashenko.gith... 更新组件 关于组件的更新,我们先看下代码里的注释: 对于已挂载组件的更新过程,React会首先调用component...

    hiyayiji 评论0 收藏0
  • 【Under-the-hood-ReactJS-Part6】React源码解读

    摘要:源码里有个独立的模块管理组件的所有子元素。第一个,实例化子元素使用并挂载它们。至于具体挂载流程,基于子元素类型的不同而有不同的挂载过程。挂载的过程基本完成了。 接上文, React流程图:https://bogdan-lyashenko.gith... 创建初始子组件 在之前的步骤里,组件本身的构建已经完成,接下去,我们分析它们的子元素。总共分为两步:挂载子元素(this.mountC...

    codergarden 评论0 收藏0
  • React学习之解读React源码

    摘要:根据的类型不同,分别实例化类。并且处理特殊属性,比如事件绑定。之后根据差异对象操作元素位置变动,删除,添加等。各个组件独立管理层层嵌套,互不影响,内部实现的渲染功能。根据基本元素的值,判断是否递归更新子节点,还是删除旧节点,添加新节点。 首先理解ReactElement和ReactClass的概念。想要更好的利用react的虚拟DOM,diff算法的优势,我们需要正确的优化、组织rea...

    developerworks 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<