Vue3 I
Vue3设计思想
- 响应式系统的重写 Vue 3 重新设计了响应式系统,采用了 Proxy API 代替了 Vue 2 中的 Object.defineProperty。这样可以提供更好的性能,并且支持更多的响应式特性。
- 更好的性能 Vue 3 引入了一些性能优化措施,例如编译器的优化、虚拟 DOM 的改进以及更高效的更新机制。这些改进使得 Vue 3 在性能方面比 Vue 2 更出色。
- Composition API Vue 3 引入了 Composition API,它是一种基于函数的 API 风格,可以更好地组织和重用组件逻辑。Composition API 提供了更灵活的组合方式,使得代码更具可读性和可维护性。
- 更好的 TypeScript 支持 Vue 3 对 TypeScript 的支持更加完善,提供了更准确的类型推断和类型检查。这使得在使用 TypeScript 开发 Vue 应用时更加方便和可靠。
- 更小的包体积 Vue 3 在设计时考虑了包体积的问题,并采取了一些措施来减小包的大小。这使得 Vue 3 在加载和运行时更加高效。
声明式框架
命令式和声明式的区别
- jq时代编写的代码都是命令式的,命令式框架重要特点就是关注过程
- 声明式框架更加关注结果。命令式的代码封装到了Vuejs中,过程靠vuejs来实现
声明式代码更加简单,不需要关注实现,按照要求填代码就可以(给上原材料就出结果)
1 2 3 4 5 6 7 8 9 10 11
| let numbers = [1,2,3,4,5] let total = 0 for(let i = 0 ; i < numbers.length; i++){ total += numbers[i] }
let total2 = number.reduce(function (memo,current){ return memo + current },0)
|
采用虚拟DOM
传统更新页面,拼接一个完整的字符串innerHTML全部重新渲染,添加虚拟DOM后,可以比较新旧虚拟节点,找到变化在进行更新。虚拟DOM就是一个对象,用来描述真实DOM的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const vnode = { __v_isVNode: true, __v_skip: true, type, props, key: props && normalizeKey(props), ref: props && normalizeRef(props), children, component: null, el: null, patchFlag, dynamicProps, dynamicChildren: null, appContext: null }
|
区分编译时和运行时
- 我们需要有一个虚拟DOM,调用渲染方法将虚拟DOM渲染成真实DOM (缺点就是虚拟DOM编写麻烦)
- 专门写个编译时可以将模板编译成虚拟DOM (在构建的时候进行编译性能更高,不需要再运行的时候进行编译,而且vue3在编译中做了很多优化)
Vue3整体架构
monorepo-管理项目
Monorepo 是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包(package)。 Vue3源码采用 monorepo 方式进行管理,将模块拆分到package目录中。
- 一个仓库可维护多个模块,不用到处找仓库
- 方便版本管理和依赖管理,模块之间的引用,调用都非常方便
Vue3项目结构

Vue3采用Typescript
Vue2 采用Flow来进行类型检测 (Vue2中对TS支持并不友好), Vue3源码采用Typescript来进行重写 , 对Ts的支持更加友好。
Vue3 开发环境搭建
搭建Monorepo环境
Vue3中使用pnpm workspace来实现monorepo (pnpm是快速、节省磁盘空间的包管理器。主要采用符号链接的方式管理模块)
全局安装pnpm
1 2 3
| npm install pnpm -g
pnpm init
|
如果不做发布可在初始化的package.json中添加 “private” : true
1 2 3 4 5
| "name": "vue3", "private": true, "version": "1.0.0", "description": "",
|
pnpm搭建monorepo环境
只需在前项目下创建pnpm-workspace.yaml
将packages下所有的目录都作为包进行管理。这样我们的Monorepo就搭建好了
1 2
| packages: - "packages/*"
|
根目录下创建所有需要管理的包的总目录packages
- 创建响应式包
packages/reactivity, pnpm init初始化, 修改package.json中name为@vue/reactivity
1 2 3 4 5
| { "name": "@vue/reactivity", "version": "1.0.0", }
|
- 创建共享方法包
packages/shared, pnpm init初始化, 修改package.json中name为@vue/shared
1 2 3 4 5
| { "name": "@vue/shared", "version": "1.0.0", }
|
安装共享模块
这时候发现共享的模块不在node_modules根目录下; 添加羞耻的提升可以将Vue3,所依赖的模块提升到node_modules中


搭建编译环境
新建文件
- 在 reactivity 新建src/index.ts
1 2 3
| import { isObject } from "@vue/shared"
export { isObject }
|
1 2 3
| export const isObject = (value) => { return value !== null && typeof value === "object" }
|
在 reactivity 中 如何通过 @vue/shared 引入shared包中的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| { "compilerOptions": { "outDir": "dist", "sourceMap": true, "target": "es2016", "module": "ESNext", "moduleResolution": "node", "strict": false, "resolveJsonModule": true, "esModuleInterop": true, "jsx":"preserve", "lib": ["ESNext","DOM"],
"baseUrl": "./", "paths": { "@vue/*":["packages/*/src"] } } }
|
这是就能正确的指向我们自己的包了
配置打包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const { build } = require('esbuild') const {resolve} = require('path')
const target = 'reactivity'
build({ entryPoints: [resolve(__dirname,`../packages/${target}/src/index.ts`)], outfile: resolve(__dirname,`../packages/${target}/dist/${target}.js`), bundle: true, sourcemap: true, format: 'esm', platform: 'browser', watch:{ onRebuild(error,result){ if (error) console.error('watch build failed:', error) else console.log('watch build succeeded:', result) } } }).then(()=>{ console.log('watching~~~') })
|
开发环境使用 esbuild 版本为 0.15.17,新版本 为 0.19.2 配置已经发生了变化, 具体可看esbuild官方文档
1 2 3
| "scripts": { "dev": "node scripts/dev.js" },
|
- reactivity/dist/index.html 引入打包文件,在浏览器打开看看时候能执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script type="module"> import { isObject } from './reactivity.js' console.log('---',isObject({a:1})) </script> </body> </html>
|