Vue3 源码如何阅读

49 阅读2分钟

源码环境

github上拉取代码, 它采用pnpm的方式去管理仓库,然后pnpm install安装依赖包,通过执行npm run build打包,会在core/packages/vue下生成dist文件(build的产物),在examples下参考其它用例开始写代码,直接浏览器打开访问,通过打断点的方式来熟悉执行流程。 image.png

初次渲染流程

image.png

入口

入口:createApp\color{red}{createApp},所在目录runtime-dom/src/index.ts 返回:app是一个对象,含有mount方法

image.png

const createApp = (...args) => {
    const app = enSureRenderer().createApp(...args)
    app.mount = function() {**}
    return app
}

app来源

app来源:enSureRenderer>createApp\color{red}{enSureRenderer -> createApp},通过上面的截图可以看出是enSureRenderer方法返回包含了createApp方法,而这里的createApp才是真正的生成app

image.png 这里的enSureRenderer -> createRenderer -> baseCreateRenderer中间只是包裹了一层,真正执行的是runtime-core/src/renderer.ts中的baseCreateRenderer

image.png 通过上图,可以看到有多个baseCreateRenderer,但前两个是声明,真正执行的是最后一个且代码量2k+,因为通过runtime-dom/src/index.ts中createApp中的函数知道它返回的有createApp对象

image.png 通过上图,它返回的含有render/hydrate/createApp三个函数

    const enSureRenderer = {
        return {
            render: **,
            hydrate: **,
            createApp: createAppAPI(render, hydrate)
        }
    }

app是什么

app是什么:在runtime-core/src/apiCreateApp.ts中的createAppAPI可以看出app是什么 image.png


上面的分析,完成Vue.createApp({**})的分析,知道了app是什么,下面分析它的mount方法

image.png

mount

mount: 通过上面可以看到2个主要的方法,一个是createVNode生成虚拟dom,还有一个render方法渲染,这里的render是createAppAPI传进来的,也就是在enSureRenderer那个地方调用的时候传的render。

image.png

vNode

vNode: 上面截图就是vNode的大概结构, type是类型判断,el是真实的DOM节点。

image.png

render

render: 在runtime-core/src/renderer.ts文件中的2320行是render方法,这里vnode不为null,它执行patch方法,patch的主要逻辑在switch方法里,根据不同的vNode中的type,来执行不同的逻辑,

image.png

patch

patch: 上图是patch的主流程。

processComponent

processComponent: 本测试代码的逻辑是执行processComponent,所以接下来继续研究processComponent,由于是初次渲染所以n1为null,执行mountComponent逻辑 image.png

image.png mountComponent: 这里mountComponent的代码中把dev相关的其它逻辑收起来,发现主逻辑主要是setupRenderEffect

image.png setupRenderEffect: 根据setupRenderEffect的逻辑可以知道,它主要执行update方法,但是update执行的是effect,effect执行的是componentUpdateFn

image.png componentUpdateFn: 发现在componentUpdateFn方法中递归又回到的patch方法里。 针对本测试,后续的流程不仔细截图表示,大概的逻辑如下:

patch -> processElement -> mountElement -> hostInsert(el, container, anchor),其中hostInsert是将真实DOM插入页面的过程