网上现有的Vue源码解析文章一搜一大批,可是为何我还要去作这样的事情呢?由于以为纸上得来终觉浅,绝知此事要躬行
。html
而后平时的项目也主要是Vue,在使用Vue的过程当中,也对其一些约定产生了一些疑问,可能官网上只会建议你这么作,可是核心实现咱们可能并不知道。好比:vue
其次,好久没有更新内容了,以前对Vue源码也是有点研究,只不过没有很体系的记录,如今抽了点时间,作了一次基础的总结吧。一方面是由于想要克服本身的惰性,另外一方面也是想从新温故一遍。node
一共分红了10个基础部分,后续还会继续记录。咱们能够先看一下概览:
git
而后咱们来看一下基础的目录:github
入口开始,解读Vue源码(二)—— new Vue 的故事数组
入口开始,解读Vue源码(三)—— initMixin 上篇浏览器
入口开始,解读Vue源码(三)—— initMixin 下篇weex
入口开始,解读Vue源码(四)—— 实现一个基础的 Vue 双向绑定函数
入口开始,解读Vue源码(六)—— $mount 内部实现 --- compile parse函数生成AST
入口开始,解读Vue源码(七)—— $mount 内部实现 --- compile optimize标记节点
入口开始,解读Vue源码(八)—— $mount 内部实现 --- compile generate 生成render函数
入口开始,解读Vue源码(九)—— $mount 内部实现 --- render函数 --> VNode
入口开始,解读Vue源码(十)—— $mount 内部实现 --- patch
世间万物的起源来自于盘古的开天辟地,Vue 项目的起源,源于一次Vue的实例化:
new Vue({ el: ..., data: ..., .... })
那么在此次实例化的过程当中,究竟发生了哪些行为?让咱们来一探究竟。打开Vue的源码文件,其核心代码在src/core
目录下。下面咱们从入口文件index.js
开始进入:(刚开始看的时候,咱们可能不太清楚每一个引用方法的具体实现,不过不要紧,咱们能够本身根据他的命名来YY一下。)
// src/core/index.js // 这里应该是咱们 Vue 核心方法 import Vue from './instance/index' // 根据命名,应该能够猜出这里是初始化一些全局API import { initGlobalAPI } from './global-api/index' // 根据命名,这里应该是获取一个Boolean类型的变量,来判断是否是ssr import { isServerRendering } from 'core/util/env' // 这里开始执行初始化全局变量 initGlobalAPI(Vue) // 为Vue原型定义属性$isServer Object.defineProperty(Vue.prototype, '$isServer', { get: isServerRendering }) // 为Vue原型定义属性$ssrContext Object.defineProperty(Vue.prototype, '$ssrContext', { get () { /* istanbul ignore next */ return this.$vnode && this.$vnode.ssrContext } }) Vue.version = '__VERSION__' export default Vue
下面咱们来一步步验证咱们的猜想,首先找到core/instance/index
文件,能够清晰的看到:
import { initMixin } from './init' import { stateMixin } from './state' import { renderMixin } from './render' import { eventsMixin } from './events' import { lifecycleMixin } from './lifecycle' import { warn } from '../util/index' function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue) export default Vue
这里简单粗暴的定义了一个 Vue Class,而后又调用了一系列init、mixin
这样的方法来初始化一些功能,具体的咱们后面在分析,不过经过代码咱们能够确认的是:没错!这里确实是导出了一个 Vue 功能类。
接下来,咱们接着看initGlobalAPI
这个东西,其实在Vue官网上,就已经为咱们说明了Vue的全局属性:
那咱们来看看,是否是这么回事(内容太多,只贴一下主要的代码):
// core/global-api/index ... export function initGlobalAPI (Vue: GlobalAPI) { // config const configDef = {} configDef.get = () => config if (process.env.NODE_ENV !== 'production') { configDef.set = () => { warn( 'Do not replace the Vue.config object, set individual fields instead.' ) } } Object.defineProperty(Vue, 'config', configDef) // 这些工具方法不视做全局API的一部分,除非你已经意识到某些风险,不然不要去依赖他们 Vue.util = { warn, extend, mergeOptions, defineReactive } // 这里定义全局属性 Vue.set = set Vue.delete = del Vue.nextTick = nextTick Vue.options = Object.create(null) ASSET_TYPES.forEach(type => { Vue.options[type + 's'] = Object.create(null) }) Vue.options._base = Vue extend(Vue.options.components, builtInComponents) // 定义全局方法 initUse(Vue) initMixin(Vue) initExtend(Vue) initAssetRegisters(Vue) }
【Vue.config】 各类全局配置项
【Vue.util】 各类工具函数,还有一些兼容性的标志位(哇,不用本身判断浏览器了,Vue已经判断好了)
【Vue.set/delete】 这个你文档应该见过
【Vue.nextTick】
【Vue.options】 这个options和咱们上面用来构造实例的options不同。这个是Vue默认提供的资源(组件指令过滤器)。
【Vue.use】 经过initUse方法定义
【Vue.mixin】 经过initMixin方法定义
【Vue.extend】经过initExtend方法定义
接下来即是提供给ssr使用的全局变量$isServer
和 $ssrContext
。 关于他们的使用,其实ssr文档也有说明:Head 管理
到这里,咱们的入口文件差很少就了解清楚了,接下来,咱们开始去了解一下 Vue class 的具体实现,其中咱们会了解到Vue的相关生命周期的知识。
文章先后也是利用碎片时间总结整理而成,有些也是翻阅了不少的资料,也有过引用巨人的段落,文章中有所标注。若是没有标注,多是本人忘记了,欢迎提醒。文章中若是有笔误或者不正确的解释,也欢迎批评指正,共同进步。
最后: