vue3源码解读--teleport

目录

    vue2源码

    vue3源码

示例

源码

    compile

        经过上一节分析,我们知道这是一次递归过程:parseChildren--parseElement--parseChildren。我们直接将代码定位到对teleport的解析过程,即当前示例中的第二次parseElement过程

        teleport开始标签的解析结果如下

        接着解析style="color:red"的标签,再次进入parseElement(此时ancestors已经有两个成员,分别为id="appWrapper"的div和teleport)

        div开始标签的解析结果如下

    接着在逐层返回前将当前作为children挂载到ancestors.pop()的元素上

    最终构建出的ast tree如下

    transform转化

        这一步就只是把一个较为纯净的ast节点绑定上一些被vue识别的附加信息,结果如下

(hoists是根节点下的子节点列表)

    generate

        首先调用genFunctionPreamble创建函数头:根节点的属性信息和根节点的子元素将作为顶层变量

       接着生成render函数

    最终编译的render函数如下

render

        从编译的结果来看,teleport相关的分别为_createBlock、_Teleport和hoisted_2(即:createElement

Vnode)

    _createBlock

        可以认为就只是创建了一个vnode,只不过它的type不再是字符串形式,而是一个对象,即

    故直接看最终生成的vnode tree,如下

    patch

        到目前为止,我还没看出来teleport在编译和render过程中有啥特别处理。如果真要去抠的话,也不过就是在碰到teleport这一内置标识时,在生成代码阶段将其从vue中导入,然后在render过程中又保留在了type属性上而已

        那必然也只能是在patch阶段根据type来做特殊了处理了吧!!

        直接跳到id="appWrapper"的div的mountChildren流程中,进入teleport的patch流程,可以看到它既没有走processElement也没有走processComponent,而是单独为teleport创建了else分支

    type即TeleportImpl对象,进入其process函数

    可以看到,一共分为了三步::创建注释节点并插入到id="#appWrapper"的div,:获取到teleport的to属性指向的dom节点并放一个空文本节点,:mountChildren进行子元素的patch

    我们知道patch中调用的是原生dom api做的插入操作,如果传入的是一个dom片段,那么页面中是不会有所改变的。但是如果传入的是一个已经在页面中展示的元素,那么它将立即插入的页面中的位置。而teleport的mountChildren传入的父元素恰好就是id="app"的根元素

    故,teleport的patch流程结束后,页面中会展示其children元素,这要比其他正常的子元素要提前一步

总结

    teleport的处理只是在patch过程中单独开了一个else分支,并在对其进行子元素patch的过程中将id="app"的根元素传递过去而不是内部维护的dom片段,这将在调用原生的dom api后直接显示在页面中,要比其他的元素提起一步被处理

    

你可能感兴趣的:(vue3源码解读--teleport)