回到技术博客

Vue3源码:createApp以及mount挂载

前言:本文探讨Vue3框架中createApp函数与mount方法的大致工作机制。首先介绍深入源码的工具和方式,而后介绍vue源码项目架构,最后详述vue创建实例应用的大致流程。

一、前序

调试准备工作

通过浏览器debugger调试的第一视角,了解代码的执行机制:

  1. vue3源码地址:https://github.com/vuejs/coregit clone到本地,然后执行下面命令即可
pnpm i
pnpm dev
  1. Live Server:vscode下这个插件,目的是运行html文件并提供热更新作用

  1. 会使用浏览器debugger功能,比较常用的有以下几点

  2. 定位源码区域,可以自行设置断点

  3. 变量区域,可以了解执行区域函数里面的具体变量值

  4. 调用栈,可以回溯调用

  5. 命令调试

[!NOTE]

F8:下一个断点处F9:下一步如果是调用函数,则进入函数内F10:下一步如果是调用函数,则跳过函数F11:和F9作用几乎一致,执行异步代码会进入,F9不会Shift+F11:跳出当前函数

源码结构

项目结构为monorepo架构方式,更加合理组织项目核心模块

  1. compiler模块:编译

  2. compiler-core:核心编译模块

  3. compiler-dom:依赖compiler-core,处理template标签的,将template内容编译成render函数

  4. compiler-sfc:解析vue文件

  5. compiler-ssr:服务端编译相关

  6. reactivity模块:响应式核心。(通过子包的形式,可以脱离vue环境,单独使用)

  7. runtime模块:运行时

  8. server-renderer:服务端渲染相关

  9. temaplate-explorer:查看模板编译结果

  10. shared:公共方法

  11. vue:框架集成入口

二、createApp

vue选项式api创建一个应用

Vue通过createApp初始化一个Vue实例,然后通过实例方法mount挂载组件。

通过debugger可以走到该部分代码

ensureRenderer

F9进入ensureRenderer函数内部:

其主要功能就是核心渲染相关,负责根据当前运行环境创建一个适合的渲染器:

  • 39行和46行代码:ensureRenderer方法只初始化一次
  • 60行和68行也就是ensureRenderer方法向外暴露出去的接口(rendercreateApp

createAppAPI(ensureRenderer所暴露出来的)

根据ensureRenderer所返回的渲染器执行createAppAPI方法创建一个实例,也就是创建Vue实例对象的核心逻辑所在。

F9进入createAppAPI函数内部:

  • 参数部分:

  • rootComponent:也就是我们所写的选项式API的“选项”

[!TIP]

为什么data属性是一个函数而不是一个对象?避免对象数据污染:如果是对象的话,只是单纯的引用值(通用同一个内存地址,一处修改,其他所有敌方都会改变),如果是函数的话,则是原始值这部分的data如何响应化?

  • 215行代码:context是用于记录组件的属性
  • 238行代码到384行代码:定义了我们常见的一些API

mount方法的重写

经过ensureRenderer方法和createApp方法所得到的实例对象app,还会经过一次mount的重写,这是为什么呢?

[!TIP]

通过解构出上述返回的app对象中的mount,重写了app.mount方法,这个和不同类型的渲染有关,比如说服务端渲染可能需要不同的挂载逻辑。通过重写mount,可以提供一个统一的API接口,这一点也体现了Vue的灵活所在。

  • 77行到103行代码:根据传进的需要挂载的DOM id值,读取DOM处理前的内容将其编译为供后续生成DOM需要的component对象

深入应用实例mount方法

mount内部,了解一下mount挂载全过程:

  • 310行代码:实例挂载只能挂载一次
  • 319行代码:根据“选项” 生成虚拟节点(vnode),同时将上述的context赋值给虚拟节点,至此,我们常说的虚拟节点到渲染真是节点的虚拟节点部分完成了

响应式也在该部分内部完成

  • _createVNode

  • createBaseVNode:这里有了vnode,但是没有实例(app._instance)

  • 343行代码:if条件里面是服务端渲染相关,暂不考虑,走到else的真实DOM渲染逻辑,也就是render逻辑

  • 346行代码:渲染

  • 349行代码:最后记录挂载的容器信息:_container

render

mount方法内部会调用render函数来将传入的模板(template或者render函数构建)生成虚拟DOM,然后通过对虚拟DOM的处理将其转换成实际的DOM结构并插入到页面中

F9走进render函数内部:

  • 参数部分

  • vnode:待渲染的虚拟节点

  • container:页面挂载容器

  • namespace

  • 2362行代码:转换的核心逻辑,其主要逻辑就是对两个虚拟节点进行**diff**比较,比较出差异部分再按需更新真实**DOM**节点

挂载前后对比

以下就是通过vue渲染前后的对比页面

— 写于生活,留给未来 —

最后更新于 2024-12-13

树下留言

LET’S TALK

文字是一次相遇。很高兴听到你的声音。

评论加载中…