项目文件结构
在Vue
项目中,所有核心的代码都是在src
目录下完成,为了更好的了解Vue
的底层实现,我们首先来了解一下src
目录下代码的组织情况,从全局入手,在脑海里留下简单的印象,方便后续的学习。(注意:当前使用Vue
的版本为2.6.12
,不同版本的内容可能会有所差异)
.
├── compiler // 编译模块:将 template 编译成为可以生成 vnode 的 render 函数
│ ├── codeframe.js
│ ├── codegen // 代码生成文件:根据 ast 树可生成 vnode 的 render代码
│ ├── create-compiler.js // 创建编译器的工厂函数
│ ├── directives // 指令解析:v-on, v-bind, v-model
│ ├── error-detector.js
│ ├── helpers.js // 编译相关方法,如属性获取等方法
│ ├── index.js // 入口文件
│ ├── optimizer.js // 编译优化:将 ast 树进行优化
│ ├── parser // html 解析文件:将 template 解析成 ast 树🌲
│ └── to-function.js // 创建编译器的工厂函数
├── core // 构造函数核心模块:构建Vue构造函数,添加原型方法,实现完成渲染流程的_init方法
│ ├── components // 自带的全局组件,如 keep-alive
│ ├── config.js // 配置相关
│ ├── global-api // 全局api,如 Vue.use, extend, mixin, component等方法
│ ├── index.js // 入口文件,在 Vue 上挂载全局方法并导出 Vue
│ ├── instance // 构造函数起始位置
│ ├── observer // 响应式原理
│ ├── util // 一些工具方法,包含 mergeOptions, nextTick 等方法的实现
│ └── vdom // 虚拟 dom
├── platforms // 平台相关,包含不同平台的不同构建入口,这里主要研究web端
│ ├── weex
│ └── web
│ ├── compiler // 与平台相关的编译
│ ├── entry-compiler.js // vue-template-compiler 包的入口文件
│ ├── entry-runtime-with-compiler.js // 构建入口,包含编译器
│ ├── entry-runtime.js // 构建入口,不包含编译器,不支持 template 转换 render
│ ├── entry-server-basic-renderer.js
│ ├── entry-server-renderer.js
│ ├── runtime // 与平台相关的构建
│ ├── server
│ └── util
│
├── server // 服务端渲染相关
├── sfc // 包含单文件组件(.vue文件)的解析逻辑,用于vue-template-compiler包
└── shared // 代码库通用代码
├── constants.js
└── util.js
以上是Vue
项目中主要文件目录,里面附带一些注释,讲解了比较主要模块的功能及作用。刚开始学习时只做简单了解即可,后面我们会逐步详细学习其中的一些模块,从而从原理级别理解整个Vue
项目的设计与实现。
Vue
的真面目
要想真正的了解Vue
是怎样的,首先我们需要找到Vue
是咋哪里被定义的。我们先找到package.json
文件下的scripts
配置。scripts
里存放的都是运行命令的别名形式,通过命令可以轻松找到对应命令执行文件的路径。
"scripts": {
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev"
}
这里当运行dev
命令实际上是运行scripts/config.js
文件,让我们找到scripts/config.js
文件。
通过运行命令参数我们可以知道process.env.TARGET
的值为web-full-dev
,因此可以在builds
里找到对应的配置文件,如下
const builds = {
'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
}
...
}
module.exports = genConfig(process.env.TARGET)
通过entry
,我们找到web/entry-runtime-with-compiler.js
文件:
import Vue from './runtime/index'
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?