網上現有的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的相關生命週期的知識。
文章先後也是利用碎片時間總結整理而成,有些也是翻閱了不少的資料,也有過引用巨人的段落,文章中有所標註。若是沒有標註,多是本人忘記了,歡迎提醒。文章中若是有筆誤或者不正確的解釋,也歡迎批評指正,共同進步。
最後: