亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

再談Vue的生命周期----結(jié)合Vue源碼

KavenFan / 3321人閱讀

摘要:中的生命周期函數(shù)也可以稱之為生命周期鉤子函數(shù),在特定的時(shí)期,調(diào)用特定的函數(shù)。吊起鉤子函數(shù)調(diào)起鉤子函數(shù)問題為什么是一個(gè)數(shù)組卸載組件,會(huì)觸發(fā)一個(gè)這行代碼之后發(fā)生了什么背后實(shí)現(xiàn)原理。

簡(jiǎn)介

關(guān)于Vue的生命周期函數(shù),目前網(wǎng)上有許多介紹文章,但也都只是分析了表象。這篇文檔,將結(jié)合Vue源碼分析,為什么會(huì)有這樣的表象。

Vue中的生命周期函數(shù)也可以稱之為生命周期鉤子(hook)函數(shù),在特定的時(shí)期,調(diào)用特定的函數(shù)。

隨著項(xiàng)目需求的不斷擴(kuò)大,生命周期函數(shù)被廣泛使用在數(shù)據(jù)初始化、回收、改變Loading狀態(tài)、發(fā)起異步請(qǐng)求等各個(gè)方面。

而Vue實(shí)例的生命周期函數(shù)有beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestpry、destroyed,8個(gè)。

本文假設(shè)讀者使用過Vue.js,但對(duì)相應(yīng)的開發(fā)經(jīng)驗(yàn)不做要求。如果你對(duì)Vue很感興趣,卻不知如何下手,建議你先閱讀官方文本

資源

以下是這篇文章所需的資源,歡迎下載。

項(xiàng)目倉(cāng)庫(kù)

Vue源碼筆記

表象

我們?cè)谠擁撁鎭硌芯?,Vue的生命周期函數(shù)究竟會(huì)在何時(shí)調(diào)用,又會(huì)有什么不同的特性。強(qiáng)烈建議你直接將項(xiàng)目倉(cāng)庫(kù)克隆至本地,并在真機(jī)環(huán)境中,跑一跑。Vue.js已經(jīng)添加在版本庫(kù)中,因此你不需要添加任何依賴,直接在瀏覽器中打開lifeCycle.html即可。

$ git clone https://github.com/AmberAAA/vue-guide
編寫實(shí)現(xiàn)組件

定義templatedata,使其在可以在屏幕實(shí)時(shí)渲染出來。

{
  //...
  template: `
    

`, data () { return { info: "" } } //... }

beforeCreate為例,定義全部的證明周期函數(shù)。

  beforeCreate() {
    console.group("------beforeCreate------");
    console.log("beforeCreate called")
    console.log(this)
    console.log(this.$data)
    console.log(this.$el)
    this.info += "beforeCreate called 
" console.groupEnd(); }
屏幕輸出

在瀏覽器中打開lifeCycle.html,點(diǎn)擊掛載組件后,屏幕依次輸出created called beforeMount called 、mounted called 。表現(xiàn)出,在掛載組件后,infocreated, beforeMount, mounted賦值,并渲染至屏幕上。但是本應(yīng)在最開始就執(zhí)行的beforeCreate卻并沒有給info賦值。
卸載組件時(shí),因?yàn)槌绦蜻\(yùn)行太快,為了方便觀察,特意為beforeDestroybeforeDestroy函數(shù)在最后添加了斷點(diǎn)。發(fā)現(xiàn)點(diǎn)擊卸載組價(jià)后,Vue在v-if=true時(shí)會(huì)直接從文檔模型中卸載組件(此時(shí)組件已經(jīng)不在document)。

控制臺(tái)輸出

控制臺(tái)輸出的內(nèi)容非常具有代表性。

我們可以發(fā)現(xiàn),控制臺(tái)按照創(chuàng)建、掛載、更新、銷毀依次打印出對(duì)應(yīng)的鉤子函數(shù)。展開來看

在觸發(fā)beforeCreate函數(shù)時(shí),vue實(shí)例還尚未初始化$data,因此也就無法給$data賦值,也就很好的解釋了為什么在屏幕上,沒有渲染出beforeCreate called。同時(shí),因?yàn)樯形幢粧燧d,也就無法獲取到$el。

在觸發(fā)created函數(shù)時(shí),其實(shí)就表明,該組件已經(jīng)被創(chuàng)建了。因此給info賦值后,待組件掛載后,視圖也會(huì)渲染出created called。

在觸發(fā)beforeMount函數(shù)時(shí),其實(shí)就表明,該組件即將被掛載。此時(shí)組建表現(xiàn)出的特性與created保持一致。

在觸發(fā)mounted函數(shù)時(shí),其實(shí)就表明,該組件已經(jīng)被掛載。因此給info賦值后,待組件掛載后,視圖也會(huì)渲染出mounted called,并且控制臺(tái)可以獲取到$el

觸發(fā)beforeUpdateupdated,分別表示視圖更新前后,更新前$data領(lǐng)先視圖,更新后,保持一致。在這兩個(gè)回調(diào)函數(shù)中,更改data時(shí)注意避免循環(huán)回調(diào)。

觸發(fā)beforeDestroydestroyed,表示實(shí)例在銷毀前后,改變$data,會(huì)觸發(fā)一次updated,因在同一個(gè)函數(shù)中(下文會(huì)介紹)回調(diào),故捏合在一起說明。

名稱 觸發(fā)階段 $data $el
beforeCreate 組件創(chuàng)建前 ? ?
created 組件創(chuàng)建后 ? ?
beforeMount 組件掛載前 ? ?
mounted 組件掛載后 ? ?
beforeUpdate 組件更新前 ? ?
updated 組件更新后 ? ?
beforeDestroy 組件創(chuàng)建前 ? ?
destroyed 組件創(chuàng)建前 ? ?
原理

Vue生命周期函數(shù)在源碼文件/src/core/instance/init.js中定義,并在/src/core/instance/init.js、src/core/instance/lifecycle.js、/src/core/observer/scheduler.js三個(gè)文件中調(diào)用了所有的生命周期函數(shù)

callHooK

當(dāng)在特定的使其,需要調(diào)用生命周期鉤子時(shí),源碼只需調(diào)用callHook函數(shù),并傳入兩個(gè)參數(shù),第一個(gè)為vue實(shí)例,第二個(gè)為鉤子名稱。如下

export function callHook (vm: Component, hook: string) {
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget()
  const handlers = vm.$options[hook]
  if (handlers) {
    //? 這里為什么是數(shù)組?在什么情況下,數(shù)組的索引會(huì)大于1?
    for (let i = 0, j = handlers.length; i < j; i++) {
      try {
        handlers[i].call(vm)
      } catch (e) {
        handleError(e, vm, `${hook} hook`)
      }
    }
  }
  if (vm._hasHookEvent) {
    vm.$emit("hook:" + hook)
  }
  popTarget()
}
耍個(gè)流氓

callHook在打包時(shí),并沒有暴露在全局作用域。但我們可以根據(jù)Vue實(shí)例來手動(dòng)調(diào)用生命周期函數(shù)。試著在掛在組件后在控制臺(tái)輸入vue.$children[0].$options["beforeCreate"][0].call(vue.$children[0]),可以發(fā)現(xiàn)組件的beforeCreate鉤子已經(jīng)被觸發(fā)了。并且表示出了與本意相駁的特性。此時(shí)因?yàn)榻M件已經(jīng)初始化,并且已經(jīng)掛載,所以成功在控制臺(tái)打印出$el$data,并在修改info后成功觸發(fā)了beforeUpdatebeforeUpdate

beforeCreatecreated

Vue會(huì)在/src/core/instance/init.js中通過initMixin函數(shù)對(duì)Vue實(shí)例進(jìn)行進(jìn)一步初始化操作。

  export function initMixin (Vue: Class) {
    Vue.prototype._init = function (options?: Object) {
      /*
        ....
      */
      vm._self = vm
      initLifecycle(vm) 
      initEvents(vm)
      initRender(vm)
      callHook(vm, "beforeCreate")
      initInjections(vm) // resolve injections before data/props
      initState(vm)   // 定義$data
      initProvide(vm) // resolve provide after data/props
      callHook(vm, "created")

      /*
        ...
      */
    }
  }

可以看出在執(zhí)行callHook(vm, "beforeCreate")之前,Vue還尚未初始化data,這也就解釋了,為什么在控制臺(tái)beforeCreate獲取到的$dataundefined,而callHook(vm, "created")卻可以,以及屏幕上為什么沒有打印出beforeCreate called。

beforeMountmounted

Vue在/src/core/instance/lifecycle.js中定義了mountComponent函數(shù),并在該函數(shù)內(nèi),調(diào)用了beforeMountmounted

  export function mountComponent (
    vm: Component,
    el: ?Element,
    hydrating?: boolean
  ): Component {
    vm.$el = el    // 組件掛載時(shí) `el` 為`undefined`

    callHook(vm, "beforeMount") // 所以獲取到的`$el`為`undefined`

    /*
      ...
    */
    // we set this to vm._watcher inside the watcher"s constructor
    // since the watcher"s initial patch may call $forceUpdate (e.g. inside child
    // component"s mounted hook), which relies on vm._watcher being already defined

    //! 挖個(gè)新坑 下節(jié)分享渲染watch。 經(jīng)過渲染后,即可獲取`$el`
    new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
    hydrating = false

    // manually mounted instance, call mounted on self
    // mounted is called for render-created child components in its inserted hook
    if (vm.$vnode == null) {
      vm._isMounted = true
      // 因?yàn)橐呀?jīng)渲染,`$el`此時(shí)已經(jīng)可以成功獲取
      callHook(vm, "mounted")
    }
    return vm
  }
beforeUpdateupdated

beforeUpdateupdated涉及到watcher,因此將會(huì)在以后的章節(jié)進(jìn)行詳解。

beforeDestroydestroyed

Vue將卸載組件的方法直接定義在原型鏈上,因此可以通過直接調(diào)用vm.$destroy()方法來卸載組件。

  Vue.prototype.$destroy = function () {
    const vm: Component = this
    if (vm._isBeingDestroyed) {
      return
    }
    // 吊起`beforeDestroy`鉤子函數(shù)
    callHook(vm, "beforeDestroy")
    vm._isBeingDestroyed = true
    // remove self from parent
    const parent = vm.$parent
    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
      remove(parent.$children, vm)
    }
    // teardown watchers
    if (vm._watcher) {
      vm._watcher.teardown()
    }
    let i = vm._watchers.length
    while (i--) {
      vm._watchers[i].teardown()
    }
    // remove reference from data ob
    // frozen object may not have observer.
    if (vm._data.__ob__) {
      vm._data.__ob__.vmCount--
    }
    // call the last hook...
    vm._isDestroyed = true
    // invoke destroy hooks on current rendered tree
    vm.__patch__(vm._vnode, null)
    // fire destroyed hook
    // 調(diào)起`destroyed`鉤子函數(shù)
    callHook(vm, "destroyed")
    // turn off all instance listeners.
    vm.$off()
    // remove __vue__ reference
    if (vm.$el) {
      vm.$el.__vue__ = null
    }
    // release circular reference (#6759)
    if (vm.$vnode) {
      vm.$vnode.parent = null
    }
  }
}
問題

vue.$children[0].$options["beforeCreate"]為什么是一個(gè)數(shù)組?

卸載組件,會(huì)觸發(fā)一個(gè)updated called?

new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)這行代碼之后發(fā)生了什么?

beforeUpdate背后實(shí)現(xiàn)原理。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/98212.html

相關(guān)文章

  • 【前端詞典】從源碼解讀 Vuex 注入 Vue 生命周期過程

    摘要:第一篇文章我會(huì)結(jié)合和的部分源碼,來說明注入生命周期的過程。說到源碼,其實(shí)沒有想象的那么難。但是源碼的調(diào)用樹會(huì)復(fù)雜很多。應(yīng)用的業(yè)務(wù)代碼逐漸復(fù)雜,事件事件總線等通信的方式的弊端就會(huì)愈發(fā)明顯。狀態(tài)管理是組件解耦的重要手段。前言 這篇文章是【前端詞典】系列文章的第 13 篇文章,接下的 9 篇我會(huì)圍繞著 Vue 展開,希望這 9 篇文章可以使大家加深對(duì) Vue 的了解。當(dāng)然這些文章的前提是默認(rèn)你對(duì) ...

    Aklman 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    sutaking 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    khs1994 評(píng)論0 收藏0
  • Vue原理】生命周期 - 源碼

    摘要:其中的標(biāo)志位什么時(shí)候設(shè)置呢,是在相應(yīng)的鉤子觸發(fā)之后,具體看下面源碼怎么執(zhí)行鉤子呢沒錯(cuò),就是下面這個(gè)函數(shù)是自己傳入的等回調(diào)那是怎么用呢比如觸發(fā)就會(huì)這么調(diào)用很簡(jiǎn)單不,直接拿到鉤子,然后遍歷執(zhí)行,綁定上下文對(duì)象。 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 ...

    siberiawolf 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<