前言

Vue3版本源码架构与Vue2版本存在非常大的不同,从使用方式的角度来讲,对它们可以简单概括为:

  • Vue2版本是命令方式使用,通过new Vue去创建Vue实例,组件中使用选项组合代码逻辑
  • Vue3版本将命令和功能API函数化,通过createApp去创建应用实例,组件中通过组合式API和选项组合代码

这里需要区分与Vue2中的一些概念,Vue2中Vue实例实际上就是组件实例,而Vue3中createApp则是创建一个上下文,称之为应用实例。组件实例是通过其他方式来获得的,例如Vue3中mount挂载后就会返回组件实例。(Vue 3.1.1版本)

createApp执行逻辑

在具体梳理createApp之前,聊聊Vue3构建输出的文件结构,不同于Vue2构建输出的UMD规范的文件,Vue3输出的文件主体就是一个IIFE函数:

var Vue = (function(exports) {...exports.createApp = createApp;...
})({});

实际上就是输出一个名为Vue的对象,该对象提供createApp函数等。

Vue.createApp的执行实际上就是调用一个createApp函数,该函数的逻辑比较清晰,这里直接贴出代码:

const createApp = ((...args) => {const app = ensureRenderer().createApp(...args);{injectNativeTagCheck(app);injectCompilerOptionsCheck(app);}const { mount } = app;app.mount = (containerOrSelector) => {// 相关处理}return app;
});

从上面逻辑可知,createApp函数的功能是返回一个app对象,并且会重写mount函数。而创建app对象又会调用其他函数来完成,相关逻辑在后面会详细梳理。

创建Renderer对象

在Vue3中存在Renderer对象的概念,实际上就是渲染器,顾名思义渲染器就是负责节点渲染。

渲染器是延迟创建的,只有在调用ensureRenderer或ensureHydrationRenderer函数才会创建,而且是单例模式。当调用Vue.createApp就会调用ensureRenderer函数,其逻辑具体如下:

function ensureRenderer() {return renderer ||(renderer = createRenderer(rendererOptions));
}function createRenderer(options) {return baseCreateRenderer(options);
}

其中rendererOptions是渲染器相关的参数,具体内容是分为两类:

  • patchProp相关:实际上是组件相关属性、事件等更新相关操作,即patch阶段的处理class、style、on事件绑定等
  • node操作相关的:节点对象的操作,例如插入、移除等

实际上Vue3允许自定义渲染器,对外暴露了createRenderer,在官网文档中有对其的定义描述:

createRenderer 函数接受两个泛型参数: HostNode 和 HostElement,对应于宿主环境中的 Node 和 Element 类型。例如,对于 runtime-dom,HostNode 将是 DOM Node 接口,HostElement 将是 DOM Element 接口。

createRenderer函数背后是调用baseCreateRenderer。

baseCreateRenderer函数

该函数的逻辑简单来说就是返回一个对象,该对象被称为渲染器对象,该对象就3个方法:

function baseCreateRenderer(options, createHydrationFns) {// 相关逻辑,其中包含相关patch阶段相关处理的函数定义return {render,hydrate,createApp: createAppAPI(render, hydrate)};
}

结合Vue2版本的逻辑可以知道,渲染器一部分承担了patch阶段的diff算法的功能和VNode到真实DOM的处理操作。这里先暂时不管这部分的功能,主要看createAppAPI的具体处理逻辑。createAppAPI就是返回一个createApp函数而已:

function createAppAPI(render, hydrate) {return function createApp(rootComponent, rootProps = null) {// 相关逻辑}
}

渲染器的createApp处理

Vue.createApp最后就是调用渲染器对象Renderer的createApp函数,其逻辑代码具体如下:

function createApp(rootComponent, rootProps = null) {// rootProps必须是对象或nullif (rootProps != null && !isObject(rootProps)) {warn(`root props passed to app.mount() must be an object.`);rootProps = null;}// 创建应用上下文const context = createAppContext();const installedPlugins = new Set();let isMounted = false;// 生成具体对象,该对象提供具体的应用API和相关属性const app = (context.app = {})return app;
}

实际上主要逻辑关注点就两处:

  • createAppContext函数调用创建应用上下文对象
  • 应用对象app的具体内容
调用createAppContext函数创建应用上下文对象

createAppContext函数的具体逻辑如下:

function createAppContext() {return {// 应用实例app: null,// 应用配置项config: {isNativeTag: NO,performance: false,globalProperties: {},optionMergeStrategies: {},errorHandler: undefined,warnHandler: undefined,compilerOptions: {}},// 混入相关mixins: [],// 全局组件components: {},// 指令directives: {},provides: Object.create(null),optionsCache: new WeakMap(),propsCache: new WeakMap(),emitsCache: new WeakMap()};
}
应用实例对象app属性

Vue.createApp函数功能就是返回应用实例对象的,该对象处理提供应用API外,还存在一些内部属性:

 const app = (context.app = {_uid: uid$1++,_component: rootComponent,_props: rootProps,_container: null,_context: context,_instance: null,version,get config() { return context.config; },set config(v) {{warn(`app.config cannot be replaced. Modify individual options instead.`);}},// 应用APIuse(plugin, ...options) {},mixin(mixin) {},component(name, component) {},directive(name, directive) {},mount(rootContainer, isHydrate, isSVG) {},unmount() {},provide(key, value) {}
});

相关应用API的说明可以具体看Vue3官方文档,而相关内部属性实际上也比较清晰,例如:

  • _context:表示应用上下文实例
  • _component:根组件
  • _container:挂载点容器Node
  • _instance:不出意外应该就是根组件实例对象了

config的额外处理

当Vue.createApp生成应用实例对象后,会针对上下文中config配置对象做额外的处理,具体代码如下:

injectNativeTagCheck(app);
injectCompilerOptionsCheck(app);

函数的定义名称是非常清晰的,上面2个函数的具体逻辑实际上就是向config对象中增加:

  • isNativeTag的检查函数:判断是否是HTML标签或SVG标签
  • isCustomElement 和 compilerOptions属性,具体是用来做什么这里暂不关心

总结

Vue.createApp是用来创建应用实例的,该应用实例提供相关的应用API和维护相关的状态。在应用实例创建过程中,会创建一个渲染器对象Renderer,针对渲染器对象有如下几点说明:

  • 渲染器对象的创建是惰性的,并且是单例模式
  • Vue3对外暴露了createRenderer API,允许开发者自定义渲染器
  • 渲染器承担Vue3视图渲染相关的功能,其中包含patch阶段的相关处理(diff算法的实现 和 DOM替换等)、应用实例的创建

对比Vue2根组件的处理逻辑(new Vue实际上就是组件实例生成的过程)中data、props、computed等相关处理逻辑,Vue3中相关处理延后到mount挂载阶段。

Vue3源码之createApp相关推荐

  1. 初学者也能看懂的 Vue3 源码中那些实用的基础工具函数

    1. 前言 大家好,我是若川.最近组织了源码共读活动.每周读 200 行左右的源码.很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习. 写相对很难的源码,耗 ...

  2. 推荐 7 个 Vue2、Vue3 源码解密分析的开源项目

    大家好,我是你们的 猫哥,那个不喜欢吃鱼.又不喜欢喵 的超级猫 ~ 1. 为什么要学习源码 ? 阅读优秀的代码的目的是让我们能够写出优秀的代码. 不给自己设限,不要让你周围人的技术上限成为你的上限.其 ...

  3. 学习尤雨溪写的 Vue3 源码中的简单工具函数

    大家好,我是若川.最近组织了源码共读活动.每周读 200 行左右的源码.很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习. 初学者也能看懂的 Vue3 源码 ...

  4. Vue3源码解析01--Vue3初探

    Vue3 源码解析 01 - Vue3 浅谈 前言 最近几个月一直忙于公司搬砖,导致都没有时间学习了.正好这段时间慢慢恢复了正常工作的作息,赶紧学习一下最新发布的 Vue3 框架. 为什么有 Vue3 ...

  5. vue3源码分析--真的有必要掌握框架的细枝末节吗?

    古人云:工欲善其事必先利其器,磨刀不误砍柴工.但是砍柴的人需要知道怎么制作刀吗? 注意:本文先分析要不要学源码,然后分析要不要掌握源码的每一个细枝末节(深究技术)!!! 为什么要学源码 为了面试被迫学 ...

  6. Vue3源码分析之打包原理

    Vue3源码分析之打包原理 如果之前你已经看过我的<Vue3源码分析之入门>,那么你可以直接阅读此篇文章 Vue3源码分析之入门 一.配置环境 1. 全局安装yarn Monorepo 管 ...

  7. Vue3源码解析之入门

    Vue3源码分析之入门 本文主要是针对想自学Vue3之类的框架源码的,却不知道如何上手的小伙伴们~ Vue3源码GitHub地址 Vue3源码克隆路径 :git@github.com:vuejs/co ...

  8. vue3源码分析——看看complier是怎么来解析的

    引言 <<往期回顾>> vue3源码分析--手写diff算法 vue3源码分析--实现组件更新 vue3源码分析--解密nextTick的实现 想知道vue3-complier ...

  9. vue3源码分析——实现slots

    引言 <<往期回顾>> vue3源码分析--rollup打包monorepo vue3源码分析--实现组件的挂载流程 vue3源码分析--实现props,emit,事件处理等 ...

  10. 深入Vue3源码,看看Vue.use后究竟发生了什么?

    从全局注册组件库入手 如果我们自定义了几个自定义组件,当我们想在.vue文件中使用它们时,需要手动import导入组件并在component中注册: 复制代码 通过Vue.use将ElementPlu ...

最新文章

  1. jsp判断语句_Java的web展现层JSP的JSTL标签详细总结
  2. R语言ggplot2可视化分面图(faceting):自定义分面图可视化、ggplot2可视化分面图并移除分面图之间的边框线条(Remove Panel Border Lines in a facet
  3. matplotlib 中子图的创建
  4. angular新版 父组件修改子组件某个div样式
  5. Vue.js教程视频
  6. 基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统)
  7. es怎么返回全部查询结果_es的返回数据结构
  8. java9 变化_Java 9 ← 2017,2019 → Java 13,来看看Java两年来的变化
  9. python常用代码大全-大神整理的python资源大全
  10. 基础学习总结(一)--工程结构与打包过程
  11. 日常管理随笔一 (转载)
  12. 第二季-专题4-我是bootloader设计师
  13. springMVC 理解大综合
  14. html制作跑马灯,html跑马灯制作
  15. 国美易卡有序实现索引,国美易卡B+树方便区间查找
  16. (附源码)spring boot通用办事流程管理软件 毕业设计211819
  17. Unity配置混合现实应用程序
  18. 手把手教你用键盘开机
  19. Stardust 案例:制作散景光斑
  20. 若依如何手动修改项目包路径呢?

热门文章

  1. 解读Depth Map Prediction from a Single Image using a Multi-Scale Deep Network (2)
  2. Windows系统、下的MySQL、版本升级、实操
  3. 用DISM修复Win10系统文件教程
  4. windows10下载安装jdk1.7教程
  5. PyQt5 电报实时聊天软件 BB-Telegram Pt.0
  6. 服务器 IIS主机的Rewrite伪静态组件下载与配置
  7. Java电子书下载地址
  8. 什么类型网站不利于seo优化
  9. HTML网站去色代码
  10. WAP技术入门(下)