01.整体变化
约 1348 字大约 4 分钟
2026-03-01
Vue3 整体变化
源码优化
Vue3 源码工程的搭建改为了 Monorepo 的形式,将模块拆分到了不同的包里面,每个包有各自的 API、类型定义以及测试。这样一类粒度更细,责任划分更加明确
Vue2 中的源码架构
Vue2 的源码全部托管在 src 目录下,然后依据功能拆分出了:
- compiler:编译器
- core:和平台无关的通用运行时代码
- platforms:平台专有代码
- server:服务端渲染相关代码
- sfc:单文件组件解析相关代码
- shared:共享工具库代码
但是各个模块无法单独抽离出来下载安装,也无法针对单个模块进行发布
其次 Vue3 使用了 Typescript 来进行静态类型检测,而在 Vue2 中使用的是 Flow.js
性能优化
笔记
- Vue3 移除了
filter、inline-template等一些冷门特性,并使用rollup进行构建,利用tree-shaking减少用户代码打包的体积 - Vue3 对数据劫持进行了优化,使用
Proxy代替Object.defineProperty - Vue3 对模板编译进行了优化,包括静态提升、预字符串化、缓存事件处理函数、Block Tree、PatchFlag
- Vue3 对== diff 算法==进行了优化,使用
快速 diff代替双端 diff
语法 API 优化
1. 优化逻辑组织
| 版本 | 方案 | 说明 |
|---|---|---|
| Vue2.x | OptionsAPI | 逻辑按 data、methods、computed、props 分散 |
| Vue3.x | OptionsAPI + CompositionAPI(推荐) | 功能逻辑集中,可复用粒度更细 |
CompositionAPI 优点:查看一个功能的实现时,不需要在文件间跳来跳去;代码复用粒度更细。
2. 优化逻辑复用
| 版本 | 方式 | 特点 |
|---|---|---|
| Vue2.x | mixin | 不清晰的数据来源、命名空间冲突、隐式跨 mixin 交流 |
| Vue3.x | 组合式函数 | 显式导入,来源清晰,无命名冲突 |
参阅 Vue 课程《细节补充 - 组合式函数》
3. 应用创建方式变化
Vue2 通过 new Vue() 创建应用,Vue3 通过 createApp() 创建应用,每个应用实例彼此隔离。
import App from './App.vue'
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
// or
new Vue({
render: h => h(App),
}).$mount('#app')import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')思考:Vue2 方式存在什么问题?
一个页面存在多个 Vue 应用时,Vue.use()、Vue.mixin()、Vue.component() 等全局配置会影响所有 Vue 应用。
<!-- vue2:app1 和 app2 共享全局配置 -->
<div id="app1"></div>
<div id="app2"></div>
<script>
Vue.use(...) // 影响所有应用
Vue.mixin(...) // 影响所有应用
Vue.component(...) // 影响所有应用
new Vue({ /* ... */ }).$mount("#app1")
new Vue({ /* ... */ }).$mount("#app2")
</script>Vue3 通过 createApp 为每个应用创建独立实例,配置互不影响:
<!-- vue3:每个应用独立配置 -->
<div id="app1"></div>
<div id="app2"></div>
<script>
createApp(根组件).use(...).mixin(...).component(...).mount("#app1")
createApp(根组件).mount("#app2") // app2 无上述配置
</script>面试题:为什么 Vue3 中去掉了 Vue 构造函数?
参考答案:
Vue2 的全局构造函数带来了诸多问题:
- 调用构造函数的静态方法会对所有 Vue 应用生效,不利于隔离不同应用
- Vue2 的构造函数集成了太多功能,不利于 tree shaking;Vue3 把这些功能以普通函数导出,能充分利用 tree shaking 优化打包体积
- Vue2 没有区分「组件实例」和「Vue 应用」:
new Vue()既是应用又是特殊组件。Vue3 中,createApp创建的是应用实例,其方法针对整个应用,概念更清晰
引入 RFC
RFC 全称 Request For Comments,是软件开发和开源项目中常用的提案流程,用于收集社区对新功能、改动或标准的意见和建议。
RFC 是一种文档格式,详细描述特性或更改的提议,讨论其动机、设计选择、实现细节及潜在影响。在讨论与反馈达成共识后,RFC 会被采纳或拒绝。
| 组成部分 | 说明 |
|---|---|
| 标题 | 简短描述提案的目的 |
| 摘要 | 简要说明提案的内容和动机 |
| 动机 | 解释为什么需要该提案,解决了什么问题 |
| 详细设计 | 深入描述提案的设计和实现细节 |
| 潜在问题和替代方案 | 讨论可能存在的问题和可考虑的替代方案 |
| 不兼容的变更 | 描述是否会引入不兼容变更,以及影响范围 |
通过 RFC,Vue 核心团队能更好地收集用户需求,开发出更符合社区期待的功能和特性。
面试题:说一下 Vue3 相比 Vue2 有什么新的变化?
参考答案:
Vue3 相比 Vue2 的整体变化可分为以下几类:
源码优化:使用 TypeScript 重构,删除冷门功能,采用 Monorepo 管理,包可独立测试发布,用户可单独引入所需模块。
性能优化:通过优化响应式、diff 算法、模板编译,Vue3 性能相比 Vue2 有明显提升,新项目建议使用 Vue3。
语法 API 优化:提出 CompositionAPI 替代 OptionsAPI,功能逻辑更集中,复用粒度更细,推荐用组合式函数替代 mixin。OptionsAPI 在 Vue3 中仍是可选编码风格。
引入 RFC:尤雨溪和核心团队采用 RFC 流程处理新功能和重大变更。
-EOF-
