前言
Vue3 进去也有好一整子了,但 Vue2 的源码原理学习,不管在升职加薪还是在另谋高就的路上,始终是一个必要的环节,正应了“面试造火箭,下班拧螺丝”这句话。只管之前对 Vue2 的源码也有学习过,然而始终没有进行一个零碎的总结,说白了就是懒。最近在掘金上看到 李永宁 大佬的 《Vue 源码解读》 系列文章后,又开始蠢蠢欲动了。这次次要是对外围实现的一个梳理,细节方面不会太过介绍。
源码地址
本次学习的 Vue源码 为 2.6.14
版本,git命令下载:
git clone https://github.com/vuejs/vue.git
这是我标记好正文的源码:
git clone https://github.com/zhangquanming/vue.git
Flow
Flow 是 facebook 出品的 JavaScript 动态类型查看工具。Vue 2.x 的源码就是利用了 Flow 做动态类型查看。相似 Flow 的工具还有如 TypeScript。大家对TS应该比拟理解,对 Flow 感兴趣能够去 官网文档 自行理解。
调试环境
源码下载后,进入根目录,装置依赖
npm i
批改dev脚本,增加 sourcemap
// package.json{"scripts": { "dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev", // ... }}
启动我的项目:
npm run dev
运行胜利,能够在 dist
目录下找到打包进去的vue.js
和 vue.js.map
文件。接下来咱们在 /examples
目录下新建文件 test.html
<!-- /examples/test.html --> <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue</title></head><body> <div id="app"> {{ msg }} </div> <script src="../dist/vue.js"></script> <script> new Vue({ el: '#app', data: { msg: 'hello vue' } }) </script></body></html>
在浏览器关上 test.html
文件,应用控制台,就能够进行断点调试,一步步看其运行过程了。
目录构造
|-- benchmarks # 性能、基准测试|-- dist # 公布目录|-- examples # 范例|-- flow # flow 类型查看|-- packages # 外围代码之外的独立库|-- scripts # 构建配置、脚本|-- src # 源码目录|-- test # 测试目录|-- types # TS 类型申明
Vue 的源码都在 src 下,上面咱们重点看下 src 目录:
src|-- compiler # 编译相干,模板解析成 ast 语法树,ast 语法树优化,代码生成等性能。|-- core # 外围代码| |-- components # 通用组件,如 keep-alive| |-- config.js # 一些默认配置项| |-- global-api # 全局API封装| |-- index.js| |-- instance # 构造函数等| |-- observer # 响应式相干| |-- util # 工具函数| `-- vdom # 虚构DOM相干|-- platforms # 不同平台的反对| |-- web # web端| `-- weex # native 客户端|-- server # 服务端渲染,这部分代码是跑在服务端的 Node.js。|-- sfc # .vue 文件解析,将 .vue 文件内容解析成一个 JS 对象。`-- shared # 共享代码,定义了一些工具办法,被浏览器端的 Vue.js 和服务端的 Vue.js 所共享的。
查找入口
通过之前运行构建命令 npm run dev
,找到构建脚本我就能发现:
// package.json{"scripts": { "dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev", // ... }}
- dev 脚本中
-c scripts/config.js
是配置文件所在。 - 参数
TARGET:web-full-dev
是输入文件配置项。
// scripts/config.jsconst builds = { // ... // Runtime+compiler development build (Browser) 'web-full-dev': { entry: resolve('web/entry-runtime-with-compiler.js'), // 构建入口 dest: resolve('dist/vue.js'), // 指标文件 format: 'umd', // 输入标准 env: 'development', alias: { he: './entity-decoder' }, banner } // ...
format
示意构建进去的文件标准:
cjs
示意 Common.js 规,用于 webpack1。es
示意 ES Module 标准,ES模块,用于 webpack2+。umd
示意 UMD 标准,兼容 cjs 和 amd ,用于浏览器。
咱们在应用 vue-cli 创立我的项目的时候,会让咱们抉择应用 Runtime Only 版本的还是 Runtime + Compiler 版本。从单个配置也标注了提醒,构建进去的文件是属于什么样的版本,咱们来看看这两个版本的区别:
- Runtime Only (仅运行时)——通常须要借助如 webpack 的 vue-loader 工具把 .vue 文件编译成 JS 渲染函数,因为构建后曾经编译实现,所以应用时只需运行时的包即可,包的体积更小。
- Runtime + Compiler (运行时+编译器)——如果没有进行预编译,或者应用了动静编译模板,如 Vue 的 template 属性并传入一个字符串, 须要在客户端进行编译,则须要含有编译器的全量包。
通过下面的单个配置,咱们就能找到入口和进口,入口为 resolve('web/entry-runtime-with-compiler.js')
,先看一下 resolve
函数:
// scripts/config.jsconst aliases = require('./alias')const resolve = p => { const base = p.split('/')[0] if (aliases[base]) { return path.resolve(aliases[base], p.slice(base.length + 1)) } else { return path.resolve(__dirname, '../', p) }}
// scripts/alias.jsconst path = require('path')const resolve = p => path.resolve(__dirname, '../', p)module.exports = { vue: resolve('src/platforms/web/entry-runtime-with-compiler'), compiler: resolve('src/compiler'), core: resolve('src/core'), shared: resolve('src/shared'), web: resolve('src/platforms/web'), weex: resolve('src/platforms/weex'), server: resolve('src/server'), sfc: resolve('src/sfc')}
最终咱们得出入口文件为: src/platforms/web/entry-runtime-with-compiler.js
, 接下来咱们就从这个入口文件登程,看一看整个 vue 的实现。
相干链接
Vue(v2.6.14)源码解毒(预):手写一个简易版Vue
Vue(v2.6.14)源码解毒(一):筹备工作
[Vue(v2.6.14)源码解毒(二):初始化和挂载(待续)]()
[Vue(v2.6.14)源码解毒(三):响应式原理(待续)]()
[Vue(v2.6.14)源码解毒(四):更新策略(待续)]()
[Vue(v2.6.14)源码解毒(五):render和VNode(待续)]()
[Vue(v2.6.14)源码解毒(六):update和patch(待续)]()
[Vue(v2.6.14)源码解毒(七):模板编译(待续)]()
如果感觉还对付的话,给个赞吧!!!也能够来我的集体博客逛逛 https://www.mingme.net/