1. vue源码分析——准备工作

本次源码分析的vue版本为2.x版本 在分析vue源码之前 我们需要先准备一些必要的知识 这样看源码时才不会出现一些疑惑 下面我们进入正题

1. 认识flow
我们都知道js是动态类型语言 它的灵活性有目共睹 但这也意味着我们在写js代码的时候很容易写出一些非常隐蔽的隐患代码 为了解决这个问题 vue使用了flow类型检查工具 之所以选择flow 主要因为babel和eslint都有对应的插件以及支持语法 非常小的改动就可以拥有静态检查能力
下面我简单写一些flow的语法:

/*@flow*/
函数
function add(x: number, y: number): number {
	return x + y;
}
限制add参数x,y必须传的数据类型为number add函数的返回值也必须为number 否则将会报错

数组
const arr: Array = [1, 2, 3];
限制声明的变量必须为数组 并且数组的元素必须为number

类和对象
class Bar {
	x: string,
	y: string | number;
	z: boolean;
	constructor (x: string, y:string | number) {
		this.x = x;
		this.y = y;
		this.z = false;
	}
}
const obj: { a: string, b: number, c: Array, d: Bar } = {
	a: 'hello',
	b: 11,
	c: ['hello', 'word'],
	d: new Bar('hello', 3)
}

null 和 undefined
var foo: ?string = null
如果想要类型T可以为null 和 undefined 只需要类似?T的格式即可

这里我就简单写了一些常用的类型语法 flow不但可以检测js所拥有的类型 也可以检测自定义类型 比如vue中定义的vnode 和 component类型等 如果想要了解更多flow的知识 可以去阅读一下官方文档:flow官网

2. 源码目录设计
简单了解了flow类型管理工具之后 我们现在来看下vue的目录设计 源码可以直接去GitHub上下载就行了 vue源码
1. vue源码分析——准备工作_第1张图片
这是下载好的源码 vue把源码放在了src下 并且根据功能把代码放到了6个不同的目录下 现在我们简单了解一些这六个目录
compiler: 和编译相关
core: 核心代码 也是我们分析的重点
platforms: 平台相关代码 web 和 weex
server:服务端渲染相关
sfc:一个简单的解释器 用来把单文件vue编译出一个js对象
shared:一个用来共享的辅助方法和一些变量

3. 源码的构建
vue源码是基于rollup构建的 rollup是一个轻量级构建工具 非常适合js库的源码构建 因为它只编译js
1. vue源码分析——准备工作_第2张图片
打开package.json 我们可以看到vue的构建配置入口在scripts/build.js文件下
1. vue源码分析——准备工作_第3张图片
build.js中拿到所有的配置 然后通过命令行参数过滤掉不需要的配置 最后调用build方法进行构建 接下来我们看下./config
1. vue源码分析——准备工作_第4张图片
1. vue源码分析——准备工作_第5张图片
我们发现这里都是一些对配置的处理 这里我们不关心 我们主要看build对象 通过build对象 我们可以找到不同版本的vue对应的入口
1. vue源码分析——准备工作_第6张图片
这里我们只关注web平台下的 vue就是通过这些入口进行构建 最后输出到dist目录下 当然这期间多次使用的resolve处理路径 这里我们并不关心 因为这不是我们的关注点 我们只需要了解构建整个脉络 如果感兴趣可以单独拿出来看看
1. vue源码分析——准备工作_第7张图片
总结:vue构建过程 通过脚本build 运行./script/build.js文件 拿到所有的配置 这些配置对应不同的入口和输出 然后通过命令行参数过滤掉不需要的配置 最后进行构建

小扩展:runtime only版本 和 runtime compiler版本
在使用vue-cli2脚手架创建项目过程中 会让我们选择vue的版本是runtime-only 还是 runtime-compiler 这里我们谈谈这两者的区别

new Vue({
	template: 'xxx'
})
runtime-only 不能使用该语法
tuntime-compiler 可以使用

runtime-compiler 就是多做了一次处理 把template编译成render函数 很显然 这个编译过程会有一定的性能损耗 并且构建出来的vue也更大 所以我们更推荐使用runtime-only
但是为了了解这个过程 我还是会分析runtime-compiler版本

4. 从入口开始 当我们引入vue时 都发生了什么
这里我们使用runtime-compiler版本作为分析目标(这次我们的目的只是为了弄清楚vue的脉络 并不会看具体逻辑)
1. vue源码分析——准备工作_第8张图片
我们打开enty-runtime-with-compiler.js
1. vue源码分析——准备工作_第9张图片
我们看到入口首先从./runtime/index文件中引入了vue 然后在vue原型上挂载了一些方法 然后导出了vue 现在我们来看./runtime/index
1. vue源码分析——准备工作_第10张图片
我们看到./runtime/index 处理也非常的简单 先从core/index中引入vue 然后对vue做了些处理 原型上添加了一些属性 然后导出vue 然后我们顺藤摸瓜看core/index
1. vue源码分析——准备工作_第11张图片
我们发现代码总是惊人的相似 首先从./instance/index中引入vue 然后初始化全局api 对vue原型做处理
然后导出vue 最后我们来看./instance/index
1. vue源码分析——准备工作_第12张图片
终于 我们看到了vue的庐山真面目 生命vue构造函数 然后做了边界处理 vue构造函数必须通过new调用 不然抛出一个警告 声明vue之后 各种init(初始化)和mixin (混入)
这里有人可能会问 vue 为什么不使用es6的class 而要 采用函数的方式声明vue呢 其实我们看下vue的结构就很容易发现原因了 我们发现vue的模块化非常清晰 每个模块都给vue添加一些原型方法和静态方法 而如果采用class 要实现这种把原型分成各个模块就比较复杂了
总结:
entry-runtime-with-compiler.js -> ./runtime/index -> core/index -> instance/index 然后再每次导入导出间给vue做各种处理(添加原型方法 添加静态方法…)

vue源码分析——准备工作 就分析到这里了如果想看更多vue源码分析系列可以进入我的博客观看更多 如果发现问题也可以私信我 谢谢大家支持

另外 源码分析借鉴huangyi老师的分析流程

你可能感兴趣的:(vue.js,javascript)