代码结构
主要看src里面的代码:
-src
-compile (编译)
-core(核心)
-components 组件
-global-api 全局api
-instance 实例
-observer 观察者
-util 使用
-vdom 虚拟DOM
-platforms 平台
-server 服务
-sfc 网络
-shared 共享
主要部分为:
src
|— compile 模板编译的代码,1.0 和 2.0 版本在模板编译这一块改动非常大
|— core/instance 生命周期,初始化入口
|— core/vdom 虚拟DOM
|— entries 编译入口文件
现在来看core里的代码
index.js
1 | // Vue 核心方法 |
处理 Vue option选项
🍃 当我们实例化一个Vue时发生了什么?
1 | import { initMixin } from './init' |
initMixin(Vue)
首先看看initMixin方法
1 | export function initMixin(Vue: Class<Component>) { |
主要是为Vue创建了一个_init方法, 该方法会在执行new Vue(options)的时候调用.下面来看每一步都做了什么:
第一步 options参数的处理
1 | if (options && options._isComponent) { // 如果传入参数是一个组件 |
此处调用了3个函数:
- initInternalComponent
- resolveConstructorOptions
- mergeOptions
让我们依次看看, 到底做了什么
✨ initInternalComponent 初始化vm.$option, 并将入参options中的值赋值给$option
1 |
|
object.constructor (返回对创建此object的数组函数的引用。)
Object.create(a) 方法创建一个新对象,使用现有的对象a来提供新创建的对象的__proto__。
✨resolveConstructorOptions 解析vm.constructor的options
1 | export function resolveConstructorOptions(Ctor: Class<Component>) { |
super关键字用于访问和调用一个对象的父对象上的函数。
其中使用了resolveModifiedOptions方法, 我们看下他干了什么
1 | // 返回Ctor.options与Ctor.sealedOptions 不一致的的属性构成的对象 |
这样看下来, 其实对Ctor类里面每个属性到底代表了没有概念(比如: options , sealedOptions 和 extendOptions), 所以我们可以先看下实现Vue 子类功能的 Vue.extend 方法initExtend方法中被定义, initExtend在initGlobalAPI方法中执行
Vue.extend
1 | Vue.extend = function (extendOptions: Object): Function { |
我们可以看到这个函数,实现了一个JS的经典继承方法,最后返回了一个继承自Super(允许开始时的this) 的子类Sub
✨mergeOptions 将两个option对象合并为新对象。用于实例化和继承的核心实用程序。
我们来看下mergeOptions的实现:
1 | export function mergeOptions ( |
默认的merge逻辑
1 | // 默认的merge逻辑 |
strats方法
1 | // 选项覆盖策略是处理如何将父选项值和子选项值合并到最终值的函数。 |
接下来看看mergeDataOrFn操作,如果options.data是个函数,主要是执行函数后,再进行data的merge
1 | export function mergeDataOrFn ( |
mergeData
1 | // 将两个数据对象递归合并在一起的帮助程序。 |
到这里我们知道了,options.data经过merge之后,实际上是一个function, 在真正调用function才会进行真正的merge。
走到这一步,我们终于把业务逻辑以及组件的一些特性全都放到了vm.$options中了,后续的操作我们都可以从vm.$options拿到可用的信息。框架基本上都是对输入宽松,对输出严格,vue也是如此,不管使用者添加了什么代码,最后都规范的收入vm.$options中。
第二步: renderProxy
定义了vm._renderProxy,这是后期为render做准备的,作用是在render中将this指向vm._renderProxy
一般而言,vm._renderProxy是等于vm的,但在开发环境,Vue动用了Proxy这个新API
1 | if (process.env.NODE_ENV !== 'production') { |