源码环境
从github上拉取代码, 它采用pnpm
的方式去管理仓库,然后pnpm install
安装依赖包,通过执行npm run build
打包,会在core/packages/vue下生成dist文件(build的产物),在examples下参考其它用例开始写代码,直接浏览器打开访问,通过打断点的方式来熟悉执行流程。
初次渲染流程
入口
入口:,所在目录runtime-dom/src/index.ts 返回:app是一个对象,含有mount方法
const createApp = (...args) => {
const app = enSureRenderer().createApp(...args)
app.mount = function() {**}
return app
}
app来源
app来源:,通过上面的截图可以看出是enSureRenderer
方法返回包含了createApp
方法,而这里的createApp才是真正的生成app
这里的enSureRenderer -> createRenderer -> baseCreateRenderer中间只是包裹了一层,真正执行的是runtime-core/src/renderer.ts中的
baseCreateRenderer
通过上图,可以看到有多个baseCreateRenderer,但前两个是声明,真正执行的是最后一个且代码量2k+,因为通过runtime-dom/src/index.ts中createApp中的函数知道它返回的有createApp对象
通过上图,它返回的含有render/hydrate/createApp三个函数
const enSureRenderer = {
return {
render: **,
hydrate: **,
createApp: createAppAPI(render, hydrate)
}
}
app是什么
app是什么:在runtime-core/src/apiCreateApp.ts中的createAppAPI可以看出app是什么
上面的分析,完成Vue.createApp({**})
的分析,知道了app是什么,下面分析它的mount方法
mount
mount: 通过上面可以看到2个主要的方法,一个是createVNode
生成虚拟dom,还有一个render
方法渲染,这里的render是createAppAPI传进来的,也就是在enSureRenderer那个地方调用的时候传的render。
vNode
vNode: 上面截图就是vNode
的大概结构, type是类型判断,el是真实的DOM节点。
render
render: 在runtime-core/src/renderer.ts文件中的2320行是render方法,这里vnode不为null,它执行patch
方法,patch的主要逻辑在switch方法里,根据不同的vNode中的type,来执行不同的逻辑,
patch
patch: 上图是patch的主流程。
processComponent
processComponent: 本测试代码的逻辑是执行processComponent
,所以接下来继续研究processComponent,由于是初次渲染所以n1为null,执行mountComponent逻辑
mountComponent: 这里mountComponent的代码中把dev相关的其它逻辑收起来,发现主逻辑主要是
setupRenderEffect
setupRenderEffect: 根据setupRenderEffect的逻辑可以知道,它主要执行
update
方法,但是update执行的是effect
,effect执行的是componentUpdateFn
componentUpdateFn: 发现在componentUpdateFn方法中
递归
又回到的patch方法里。
针对本测试,后续的流程不仔细截图表示,大概的逻辑如下:
patch -> processElement -> mountElement -> hostInsert(el, container, anchor)
,其中hostInsert是将真实DOM插入页面的过程