多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 认识Flow Flow是facebook出品的Javascript静态类型检查工具,Vue.js的源码利用了Flow做了静态类型检查。 ### 为什么用? Javascript是动态类型语言,灵活性强,但过于灵活的副作用是很容易写出非常隐蔽的隐患代码,在编译器甚至看上去都不会报错,但是在运行阶段就可能出现各种奇怪的bug 类型检查是当前动态类型语言的发展趋势,就是在编译期禁止发现(由类型错误引起的)bug,又不影响代码运行。使编写的Javascript具有和编写java等强类型语言相近的体验。 项目越复杂就越需要工具来保证项目的维护性和增强代码的可读性。 Vue 2.0重构时,在ES2015基础上,**除了ESLint保证代码风格,也引入Flow做静态类型检查**。 ## 源码目录设计 ![](https://box.kancloud.cn/ab67af35f222ca545f145cef2fc0dd81_339x181.png) * compiler:编译相关代码,包括把模板解析成AST语法树,AST语法优化,代码生成等功能。 编译的工作可以在构建时做(webpack,vue-loder等),也可以在运行时做,编译时一项耗性能的工作。 * core :vue的核心代码,包括内置组件,全局API封装,Vue实例化,观察者,虚拟DOM,工具函数等 * platform vue是一个跨平台的mvvm框架,可以跑在web上,也可以配合weex跑在native客户端上。 * server:vue2.0支持了服务端渲染,素银服务端渲染相关逻辑都在这个目录。这部分代码是跑在服务端的node.js。服务端渲染:把组件渲染为服务端的HTML字符串,将他们直接发送到浏览器,最后将静态标记”混合“为客户端上完全交互的应用程序 * sfc:通常vue都会借助webpack构建,然后通过.vue单文件来编写组件,这个目录的代码逻辑会把.vue文件内容解析成一个Javascript的对象。 * shared 共享 ## vue.js源码构建 Vue.js源码是基于Rollup构建的,构建的相关配置都在scripts目录下。 Vue两个版本: Runtime Only:**借助webpack和vue-loader**把我们vue文件编译成JavaScript,(浏览器不认识vue文件),把template模板编译成render函数,编译后是一个render函数的版本,所以Runtime Only是不带编译的,**编译是在离线的时候做**。因为是**在编译阶段做的**,所以它只包含运行时的Vue.js,因此代码体积也会更轻量。 推荐:体积小 Runtime+Compiler:可以不对代码做预编译,也可以用vue单文件方式。我们如果没有对代码做预编译,但又使用了Vue的template属性,并传入一个字符串,则需要在客户端编译模板。(是在**运行的时候**做的)。 ## 从入口开始 来分析 Runtime + Compiler 构建出来的 Vue.js,它的入口是`src/platforms/web/entry-runtime-with-compiler.js`: 当我们的代码执行`import Vue from 'vue'`的时候,就是从这个入口执行代码来初始化 Vue,它实际上就是一个用 Function 实现的类,我们只能通过`new Vue`去实例化它。 为何 Vue 不用 ES6 的 Class 去实现呢? 我们往后看这里有很多`xxxMixin`的函数调用,并把`Vue`当参数传入,它们的功能都是给 Vue 的 prototype 上扩展一些方法(这里具体的细节会在之后的文章介绍,这里不展开),Vue 按功能把这些扩展分散到多个模块中去实现,而不是在一个模块里实现所有,这种方式是用 Class 难以实现的。这么做的好处是非常方便代码的维护和管理,这种编程技巧也非常值得我们去学习。 ***** 定义`--patch--`,`$mount`方法 Vue是一个function,必须实例化,new Vue 不使用class的原因: **每一个mixin就是往Vue的原型上混入一些原型上的方法,用ES6实现这个效果比较难写,用ES5实际上可以往Vue原型上挂载很多方法,并可以放在不同文件下。方便代码管理** initMixin:往Vue.prototype上挂了_init方法 stateMixin:往Vue.prototype上挂载一些方法`$set,$delete`, eventsMixin lifecycleMixin: renderMixin: **Vue本身是一个函数,可以理解为一个类,这个类上面挂了很多原型方法,通过mixin等混入。** 初始化**全局API**:往Vue上挂载一些静态属性。 Vue.set,Vue.delete,Vue.nextTick,Vue.options Vue.options:可以合并一些方法,比如**component,directive,filter**(全局方法) **内置组件:keep-alive,通过Vue.extend方法扩展的**。 Vue.use: **在import Vue的过程中: 初始化过程中,完成了全局方法的定义,之后才可以在代码中使用,在import Vue中完成的。** Vue初始化的两个步骤: **1. 找到Vue的定义,并通过mixin方法,挂载了很多原型方法。 2. 通过initGlobalAPI,给Vue挂载了很多静态方法。** 静态方法:为类所有,可以通过类来调用。 **Vue.use,Vue.set,Vue.componets,Vue.directives,vue.filters,Vue.defineReative,Vue.extend,Vue.mergeOptions,vue.version,Vue.config**