React源代码解析(3):组件的生命周期

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-30 09:13   78   0

这一章可能比较长,因为这一章我会把生命周期,transaction,setState放到一起说明. 组件的生命周期分为二个部分

  1. 组件的挂载
  2. 组件的更新

组件的挂载

上一章对于组件的挂载已经做了详细的说明,但是涉及到组件生命周期部分被略过.接下来我将对其深入解析. 组件的挂载涉及到二个比较重要的生命周期方法componentWillMountcomponentDidMount.

componentWillMount

对于componentWillMount这个函数玩过React的都知道他是组件render之前的触发. 但是如果我再具体点呢. 是在实例之前?还是实例之后?还是构建成真实dom之前?还是构建成真实dom之前,渲染之前?估计很多人不知道吧.所以在面试的时候无论你对React有多熟,还是尽量不要说"精通"二字.(大佬除外)

componentWillMount是组件更新之前触发,所以直接从ReactCompositeComponent.mountComponent里面找

// this.performInitialMount

if (inst.componentWillMount) {
    debugger
    if ("development" !== "production") {
        measureLifeCyclePerf(
            function() {
                return inst.componentWillMount();
            },
            debugID,
            "componentWillMount"
        );
    } else {
        inst.componentWillMount();
    }
    // When mounting, calls to `setState` by `componentWillMount` will set
    // `this._pendingStateQueue` without triggering a re-render.
    if (this._pendingStateQueue) {
        inst.state = this._processPendingState(
            inst.props,
            inst.context
        );
    }
}
复制代码

代码在performInitialMount函数里面,所以在实例之后,虚拟dom构建真实dom之前触发的

componentDidMount

直接看代码吧

var markup;
if (inst.unstable_handleError) {
    markup = this.performInitialMountWithErrorHandling(
        renderedElement,
        hostParent,
        hostContainerInfo,
        transaction,
        context
    );
} else {
    markup = this.performInitialMount(
        renderedElement,
        hostParent,
        hostContainerInfo,
        transaction,
        context
    );
}
if (inst.componentDidMount) {
        if ("development" !== "production") {
            transaction
                .getReactMountReady()
                .enqueue(function() {
                    measureLifeCyclePerf(
                        function() {
                            return inst.componentDidMount();
                        },
                        _this._debugID,
                        "componentDidMount"
                    );
                });
        } else {
            transaction
                .getReactMountReady()
                .enqueue(
                    inst.componentDidMount,
                    inst
                );
        }
    }
复制代码

它是出现在markup(真实dom)之后.但是肯定不会在这里面执行,因为在markup还没插入到container里面呢。回顾一下上一章的内容MountComponentIntoNode方法mountComponent之后还有个setInnerHTML(container, markup)只有这个函数执行完之后componentDidMount才能执行.

注意performInitialMount方法 看看下面的代码

class A extends React.Component {
    render(){
        return <K />
    }
}
<App>
    <A />
</App>
复制代码

this.componentDidMount的执行顺序是K-->A--->App<(ljs-title">function() { measureLifeCyclePerf( inst.componentDidUpdate.bind( inst, prevProps, prevState, prevContext ), _this2._debugID, "componentDidUpdate" ); }); } else { transaction .getReactMountReady() .enqueue( inst.componentDidUpdate.bind( inst, prevProps, prevState, prevContext ), inst ); } } 复制代码

是不是感到非常眼熟,跟组件的挂载非常类似, 先执行componentWillUpdate方法然后通过_updateRenderedComponent递归的更新组件,更新完成之后执行transaction里面的Wrapper中的close方法, close将释放componentDidUpdate的队列.

说到这里,组件的生命周期也就是讲完了. 还有三个比较核心的点.

  1. diff算法 (同级之间的比较,更新前后的虚拟dom到底是如何对比的)
  2. 事件系统, (React合成系统到底是什么?)
  3. fiber架构 (React16版本革命性的变革)
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP