vue源碼解析(二)

先決條件
  • 需要能夠熟悉使用 vue ,了解vue屬性和方法臭脓。
  • 帶著問題去看源碼
  • 熟悉ES6或者Typescript語法
  • 確定源碼的版本僚楞,我看的是 2.6.12
問題
  • vue在初始化的時候都做了什么事情别凤?
vue的初始化

上個章節(jié)我們知道了vue源代碼的入口文件src/platforms/web/entry-runtime.js

import Vue from 'core/index'
import config from 'core/config'
import { extend, noop } from 'shared/util'
import { mountComponent } from 'core/instance/lifecycle'
import { devtools, inBrowser } from 'core/util/index'

import {
  query,
  mustUseProp,
  isReservedTag,
  isReservedAttr,
  getTagNamespace,
  isUnknownElement
} from 'web/util/index'

import { patch } from './patch'
import platformDirectives from './directives/index'
import platformComponents from './components/index'

// install platform specific utils
Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isReservedAttr = isReservedAttr
Vue.config.getTagNamespace = getTagNamespace
Vue.config.isUnknownElement = isUnknownElement

// install platform runtime directives & components
extend(Vue.options.directives, platformDirectives)
extend(Vue.options.components, platformComponents)

// install platform patch function
Vue.prototype.__patch__ = inBrowser ? patch : noop

// public mount method
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating)
}

第一行import Vue from 'core/index'川背,就引入了vue的主體贰拿,并在這個主體上進行擴展。比如熄云,添加一些平臺的特定方法 vue.config.mustUseProp膨更,不過,我們平常并不會用到缴允。
要注意的是荚守,在入口文件給vue綁定了原型方法 $mount珍德,這個在后面會用到。


核心文件介紹

上面的代碼矗漾,很多都引入了core文件锈候,我們了解下 core 這個文件夾的每個文件的作用。

core

core翻譯過來就是 核心 的意思敞贡,vue的核心代碼都在這個文件夾內(nèi)泵琳。

  • components 定義組件代碼
  • global-api 給vue設(shè)置全局配置項,全局API方法等誊役,比如Vue.set Vue.nextTick
  • instance 創(chuàng)建vue初始化函數(shù)获列,實例方法,實例屬性和構(gòu)建vue的生命周期蛔垢,這個就很重要了击孩。
  • observer 創(chuàng)建vue中常用的觀察者模型,我們的雙向數(shù)據(jù)綁定和一些watch監(jiān)聽都依賴于它
  • util 創(chuàng)建一些工具函數(shù)提供給源碼使用
  • vdom 創(chuàng)建vue的虛擬DOM
  • config.js 常用的配置項給源碼使用
  • index.js core 的入口代碼文件

我們看下 core 的入口代碼啦桌,第一行 import Vue from './instance/index' 還是在引用vue主體溯壶,目前還是沒有找到Vue主體。

core/index.js
這個core/index.js的作用甫男,第一是通過initGlobalAPI來初始化Vue全局的配置項和全局API(具體請看vue的文檔);第二是定義Vue的原型方法 $isServer 验烧,$ssrContext板驳, FunctionalRenderContext


Vue主體函數(shù)

通過入口文件碍拆,我們繼續(xù)向里面深挖 若治,看到這里老鐵們,我們找到了Vue的主體了感混。

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')
  }

  // 執(zhí)行 initMixin中定義的原型方法
  this._init(options)
}

// 定義初始化函數(shù)端幼,實例方法,觸發(fā)生命周期鉤子函數(shù)
initMixin(Vue)

// 定義實例屬性弧满,$data, $props 和 實例方法 $set(), $delete(), $watch()
stateMixin(Vue)

// 定義實例方法/屬性 $on(), $once(), $off() 和 $emit()
eventsMixin(Vue)

// 定義實例方法/生命周期 $forceUpdate(), $destory()婆跑,_update()
lifecycleMixin(Vue)

// 定義實例方法/生命周期  $nextTick(),
// 并且定義內(nèi)部方法 _render()
renderMixin(Vue)

export default Vue

function Vue() {....} 就是構(gòu)建Vue的主體函數(shù)。
這個文件里面有很多方法比如initMixin(), stateMixin(), eventsMixin()等 都是圍繞者主體函數(shù)來構(gòu)建Vue實例方法庭呜,內(nèi)部方法或者添加鉤子函數(shù)的滑进,不過這都不重要。

在這里的重點是募谎,當我們使用vue的時候 扶关,它執(zhí)行了 function Vue() {....} 主體函數(shù)里面的 this._init() 方法。

 new Vue({
   data: {}
 })
調(diào)用了 this._init(options)

initMixin() 定義了 this._init()方法数冬。

export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    vm._uid = uid++
    // a flag to avoid this being observed
    vm._isVue = true
   
    // 定義實例屬性 $options节槐,可以重置一些自定義property屬性和方法,比如自定義 created(),methods() 和 data
    // vm.constructor 是在 initGlobalAPI 定義的
    vm.$options = mergeOptions(
      resolveConstructorOptions(vm.constructor),
      options || {},
      vm
    )

    // expose real self
    vm._self = vm

    // 定義實例屬性 $root, $parent, $children, $refs
    // 并初始化實例的一些內(nèi)部屬性 _watcher铜异,_inactive地来, _isMounted 等
    initLifecycle(vm)

    // 初始化事件
    initEvents(vm)

    // 定義實例屬性 $slots, $scopedSlots, $createElement, $attrs, '$listeners
    initRender(vm)

    // 觸發(fā)鉤子函數(shù) beforeCreate
    callHook(vm, 'beforeCreate')

    // provide 和 inject 主要在開發(fā)高階插件/組件庫時使用。并不推薦用于普通應(yīng)用程序代碼中熙掺。
    initInjections(vm) // resolve injections before data/props

    // 初始化狀態(tài)未斑,比如 data, props, methods, computed和watch
    initState(vm)

    // provide 和 inject 主要在開發(fā)高階插件/組件庫時使用。并不推薦用于普通應(yīng)用程序代碼中币绩。
    initProvide(vm) // resolve provide after data/props

    // 當數(shù)據(jù)蜡秽,方法等必要屬性都初始化后,觸發(fā)created鉤子函數(shù)
    callHook(vm, 'created')

    // 將實例掛載到Dome上
    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}

_init() 函數(shù)做了很多事了缆镣,初始化事件芽突,添加了很多實例屬性,觸發(fā)鉤子函數(shù)董瞻,初始化數(shù)據(jù)寞蚌,對數(shù)據(jù)做監(jiān)聽,最后把實例通過$mount()掛載到dome上钠糊。$mount()函數(shù)在一開始src/platforms/web/entry-runtime.js代碼文件被定義挟秤。


總結(jié):

從找到編譯的源代碼入口src/platforms/web/entry-runtime.js,到最后找到 Vue的主體函數(shù)抄伍。vue初始化的主線都比較清晰艘刚,感覺就像撥洋蔥,在核心里創(chuàng)建函數(shù)主體截珍,然后給函數(shù)主體一層一層添加需要的方法和屬性攀甚。下一節(jié)看vue的生命周期是如何形成的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岗喉,一起剝皮案震驚了整個濱河市秋度,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钱床,老刑警劉巖荚斯,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诞丽,居然都是意外死亡鲸拥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門僧免,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刑赶,“玉大人,你說我怎么就攤上這事懂衩∽策叮” “怎么了金踪?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長牵敷。 經(jīng)常有香客問我胡岔,道長,這世上最難降的妖魔是什么枷餐? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任靶瘸,我火速辦了婚禮,結(jié)果婚禮上毛肋,老公的妹妹穿的比我還像新娘怨咪。我一直安慰自己,他們只是感情好润匙,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布诗眨。 她就那樣靜靜地躺著,像睡著了一般孕讳。 火紅的嫁衣襯著肌膚如雪匠楚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天厂财,我揣著相機與錄音芋簿,去河邊找鬼。 笑死蟀苛,一個胖子當著我的面吹牛益咬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帜平,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼梅鹦!你這毒婦竟也來了裆甩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤齐唆,失蹤者是張志新(化名)和其女友劉穎嗤栓,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箍邮,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡茉帅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锭弊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堪澎。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖味滞,靈堂內(nèi)的尸體忽然破棺而出樱蛤,到底是詐尸還是另有隱情钮呀,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布昨凡,位于F島的核電站爽醋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏便脊。R本人自食惡果不足惜蚂四,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哪痰。 院中可真熱鬧遂赠,春花似錦、人聲如沸妒御。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乎莉。三九已至送讲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惋啃,已是汗流浹背哼鬓。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留边灭,地道東北人异希。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像绒瘦,于是被迫代替她去往敵國和親称簿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容