资讯专栏INFORMATION COLUMN

【Under-the-hood-ReactJS-Part3】React源码解读

antyiwei / 3150人阅读

摘要:接上文,流程图挂载是我们重点关注对象之一。赋值实例更新器流程图中返回的对象,其实就是模块。目前我们并不会使用,但是我们必须了解的是,非常非常重要,大名鼎鼎的方法就会使用到这个。这个方法是我们目前碰到的第一个生命周期事件钩子。

接上文,

React流程图:
https://bogdan-lyashenko.gith...

挂载

componentMount是我们重点关注对象之一。 这个方法最重要的部分就是ReactCompositeComponent.mountComponent.
如果你还有印象,我提到过第一个被压入到组件树里的组件是TopLevelWrapper(React内部类)。在mountComponent中,我们将挂载它。
但是,这个内部类是一个空的包装类。对于调试来说毫无意义,它完全不影响流程。所以,我们暂且跳过它,先对它的子组件进行研究。

挂载一个组件树的过程大致如下:挂载父亲组件,然后挂载它的子组件,然后是子组件的子组件,以此类推。当TopLevelWrapper挂载后,它的子组件(ReactCompositeComponent,负责管理ExampleApplication)也会进入到相同的步骤。

我们回到ReactCompoiteComponent一探究竟。这里面有一些关键点需要注意,接下去我们会详细的讨论里面的逻辑。

赋值实例更新器

流程图中 transaction.getUpdateQueue()返回的对象updateQueue,其实就是ReactUpdateQueue模块。那么会为什么在这里要赋值updateQueue呢?这是因为ReactCompositeComponent(我们正在研究的类)是各个平台都需要使用的,但是updateQueue则在不同平台有不同实现,所以需要我们动态的在挂载过程中根据不同的平台赋予不同的值。

目前我们并不会使用updateQueue,但是我们必须了解的是,updateQueue非常非常重要,大名鼎鼎的setState方法就会使用到这个updateQueue。

在这个阶段,除了对updateQueue的赋值,还会有组件实例(自定义组件)被props,context,refs扩展的过程。

看下如下代码:

// src
endererssharedstack
econcilerReactCompositeComponent.js#255
// These should be set up in the constructor, but as a convenience for
// simpler class abstractions, we set them up after the fact.
inst.props = publicProps;
inst.context = publicContext;
inst.refs = emptyObject;
inst.updater = updateQueue;

这个步骤之后,就可以通过类似this.props的方式来让实例获取props等属性了。

创建ExampleApplication实例

在流程图中,通过调用_constructComponent方法和其他几个构造方式,一个新的ExampleApplication实例就被创建出来了。我们在组件构造函数里写的代码往往也是在这里被调用的。 这里,是我们自己写的代码第一次真正被React系统调用的地方。

执行初始挂载

现在我们开始挂载过程,第一件事就是调用componentWillMount(前提当然是如果有组件代码里有指定)。这个方法是我们目前碰到的第一个生命周期事件钩子。当然,在后面你也会看到componentDidMount方法。在这里,我们并不直接执行它们,我们只是将它们押入到事务队列里。它们的真正的执行在非常后面,是在挂载操作完成之后才执行的。你可以在componentWillMount里调用setState方法,然后state会重新计算,但是render方法并不会被调用(如果在这里调用render方法是毫无意义的,因为组件都没挂载到DOM树上呢)

官方文档表达了类似的意思

当挂载事件发生前,componentWillMount方法会被立刻调用。它的调用在render方法之前,因此,在这里调用setState不会触发重新渲染(componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state in this method will not trigger a re-rendering.)

看下源码里是怎么做的

// src
endererssharedstack
econcilerReactCompositeComponent.js#476
if (inst.componentWillMount) {
    //..
    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);
    }
}

当state重新计算后,我们就会调用render方法了,就是我们在我们自定义组件里定义的render方法。React又一次使用了我们的代码。

接下去,我们将会创建一个React组件实例,嗯,又创建一次。我们之前已经调用过一次this._instantiateReactComponent了,为什么这里又要调用一次呢?这是因为,前一次的调用,是创建一个ExampleApplication组件对应的ReactCompositeComponent实例,现在,我们则是根据我们组件的render方法中返回的元素,创建子组件对应的虚拟DOM实例。在我们的列子中,render方法返回了一个div,所以,虚拟DOM创建一个ReactDOMComponent的实例。当这个实例创建后,我们会又一次调用ReactReconciler.mountComponent方法,但这次是一个创建内部实例但过程,我们传递的是一个ReactDOMComponent的实例。 然后,继续调用它的mountComponent方法。。。
(未完待续)

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

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

相关文章

  • Under-the-hood-ReactJS-Part6】React源码解读

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

    codergarden 评论0 收藏0
  • Under-the-hood-ReactJS-Part9】React源码解读

    摘要:当鼠标事件发生时,组件的最外层会进行处理,然后通过几层包装器的处理后,会开始进行批量更新操作。在这之后,会将这些事件处理成常见到样子。 接上文, React流程图:https://bogdan-lyashenko.gith... 回到最初 在流程图中,也许你已经注意到,setState方法可以通过几种方式触发,更准确的说,可以分为是否由外部引起的(也就是是否由用户触发)。让我们看下如下...

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

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

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

    摘要:接上文,流程图我们已经知道挂载的工作流程,现在我们换个方向研究下方法,这个也是的重要组成部分。这个问题,我们会在下一篇文章中进行解答。。。 接上文, React流程图:https://bogdan-lyashenko.gith... this.setState 我们已经知道挂载的工作流程,现在我们换个方向研究下--setState方法,这个也是React的重要组成部分。 首先,为什么我...

    zhoutk 评论0 收藏0
  • Under-the-hood-ReactJS-Part13React源码解读

    摘要:接着,将返回的元素和之前的进行比较的,以验证是否真的需要更新。我们看下代码,代码比较简单好,对应于我们的这个列子,我们对于方法的更改并不会对方法造成影响。所以我们进入下一步,也就是对于节点的更新。 接上文, React流程图:https://bogdan-lyashenko.gith... 如果组件真的需要更新 在组件刚开始更新过程时,如果有定义componentWillUpdate方...

    jerryloveemily 评论0 收藏0
  • Under-the-hood-ReactJS-Part4】React源码解读

    摘要:接上文,流程图子组件挂载我们继续探究方法。对于我们的实例代码而言,就是标签,所以没有额外的处理过程。属性验证紧接着的被调用的验证方法用于确保被正确设置,否则,会抛出异常。 接上文, React流程图:https://bogdan-lyashenko.gith... 子组件挂载 我们继续探究mount方法。 如果渲染的标签里有复杂的html标签,如video,form,textarea等...

    evin2016 评论0 收藏0

发表评论

0条评论

antyiwei

|高级讲师

TA的文章

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