【Vue源碼探究一】當咱們引入Vue,咱們引入了什麼?

源碼版本:2.0.5前端

構造器、實例、選項

讓咱們用一段demo展現一下這三個概念:vue

//HTML
<div id="app">
  {{ message }}
</div>
//JS
var vm = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

其中:api

  • Vue: Vue的構造器瀏覽器

  • vm : 實例 (實例名能夠任意取,這裏咱們便於理解保持和vue文檔一致)app

  • new Vue(options): 選項(options)即爲傳入構造器裏的配置選項。(data, methods,computed,created...)函數

當咱們瞭解這三個概念,將有助於咱們去理解vue的api文檔工具

Vue 的開放api

跳轉到vue的文檔
clipboard.png學習

  1. 全局配置: 以 Vue.config.xx 的形式去訪問和修改ui

  2. 全局API: 以Vue.xx 的形式去訪問和修改this

  3. 選項: 以 var vm = new Vue(options) 的形式將options傳入構造器

  4. 實例屬性/方法: 以vm.$xx的方式去訪問 (前綴$,爲了不用戶data/methods等解析後綁定的api 和 默認api衝突)

從api文檔中咱們能夠了解到,當咱們引入vue.js, 咱們僅僅引入了一個構造函數(Vue)
引入了構造函數後,咱們有幾種使用方式

最多見的使用方式: var vm = new Vue(options)

將咱們自定義的選項,傳入構造器。 當new Vue(options)時,會自動運行vm._init方法

  • 解析各類選項

  • 調用beforeCreate 和created 上綁定的鉤子函數

  • 將數據項(data,computed,props)和methods等綁到實例上

  • 調用vm.$mount方法,來執行模板渲染

  • 返回一個實例對象 vm

實際上,咱們使用vue.js來開發時,主要就是配置不一樣的options提供Vue構造器解析,實現不一樣的業務功能。

經過更改Vue.config來進行全局配置

在選項內部可使用 Vue 和 vm 來調用構造器和實例上的方法

Vue源碼是怎麼開放這些api的

主入口

src/core/index.js

import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'

initGlobalAPI(Vue)

Object.defineProperty(Vue.prototype, '$isServer', {
  get: isServerRendering
})

Vue.version = '__VERSION__'

export default Vue

Vue源碼的主入口主要作三件事
1.引用 ./instance/index 中暴露的Vue構造器
2.調用initGlobalAPI方法,定義全局資源
3.暴露Vue

initGlobalAPI

src/core/global-api/index.js

//源碼有點長,我去掉了引用部分和一些註釋。
export function initGlobalAPI (Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      util.warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  Object.defineProperty(Vue, 'config', configDef)
  Vue.util = util
  Vue.set = set
  Vue.delete = del
  Vue.nextTick = util.nextTick

  Vue.options = Object.create(null)
  config._assetTypes.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  })

  Vue.options._base = Vue

  util.extend(Vue.options.components, builtInComponents)

  initUse(Vue)
  initMixin(Vue)
  initExtend(Vue)
  initAssetRegisters(Vue)
}

initGlobal的代碼就是對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方法定義

這些定義的全局api可好玩了,日常咱們可能是用實例上的方法。其實構造器上也綁了很多好用的方法。
有興趣的同窗,能夠用下方代碼去探究一下

在你的vue項目裏,谷歌命令行鍵入
Object.getOwnPropertyNames(Vue)  //能夠看定義在對象上的全部屬性名/方法名
Vue.config
Vue.util
Vue.set.toString()  //咱們日常在控制檯上是看不了一個函數到底源碼怎麼樣的,用toString()就能夠啦

Vue構造器的定義

src/core/instance/index.js

//構造函數,當new Vue(options) 會自動執行這個函數
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)

這裏就不一個一個函數展開了
構造函數裏其實就一句話,this._init(options)

initMixin之類的方法,定義了實例上的方法,下面給出一個探索地圖,以供探究源碼

clipboard.png

咱們能夠看到 以 "_"爲開頭的方法,多半是Vue內部使用,但不公開的api。
以「$」 爲開頭的方法,是文檔中公開給用戶使用的默認api

至此,咱們對Vue的結構有了個初步的瞭解,以及相關api的原始出處有了初步瞭解。

在學習的過程當中,參考了兩位大牛的文章,收益良多
囧克斯 Vue.js源碼學習筆記
王鶴 Vue.js 2.0源碼解析以前端渲染篇

相關文章
相關標籤/搜索