日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

Vue生命周期详解 对应代码解析

發布時間:2023/12/2 vue 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Vue生命周期详解 对应代码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

-使用GitHub閱覽

對于Vue的實例,比如

const app = new Vue({...})

瀏覽器解析到這段代碼的時候,自動執行beforeCreate => created => beforeMount => mounted方法,每當data的某個屬性值更改了,比如==app.mes = "hi"==,自動執行beforeUpdate => updated方法。

beforeCreate:

el : undefined data : undefined message: undefined

created:

el : undefined data : [object Object] message: hi

beforeMount:

el : [object HTMLDivElement] <div id="app"><p>{{ message }}</p></div> data : [object Object] message: hi

mounted:

el : [object HTMLDivElement] <div id="app"><p>hi</p></div> data : [object Object] message: hi

當需要銷毀這個實例的時候,需要手動執行app.$destroy()。然后Vue此時會自動調用beforeDestroy、destroyed方法。

一旦組件被銷毀,它將不再響應式,即更改data的屬性值,比如app.mes = "hello",頁面不會同時被更新,頁面上的數據任然顯示的是 hi

此時需要手動調用app.$mount(),這個方法在這個時候被手動調用的時候,Vue會自動按照下面的順序執行以下方法: beforeMount => beforeUpdate => updated => mounted。

此時,我們會發現頁面變成了hello 我的理解是,雖然之前app被銷毀了,但是對于mes屬性的dep里面,通過監控它的watcher,仍然是變成了“hello”,但是不會調用底層的compile(this.cb)來渲染視圖。而當手動調用app.$mount()的時候,它的compile方法被激活,又變成響應式的了。 當我們調用destroy方法的時候,其實調用了app._watcher的teardown方法,下面代碼所示(在執行這個destroy之前,我們調用了callHook這個鉤子函數):

Vue.prototype.$destroy = function () {var vm = this;if (vm._isBeingDestroyed) {return}callHook(vm, 'beforeDestroy');if (vm._watcher) {vm._watcher.teardown();}var i = vm._watchers.length;while (i--) {vm._watchers[i].teardown();} }

_watcher的active值被置為false,然后調用removeSub將該watcher所依賴的訂閱器全都退訂(從每個dep的subs數組中移除)。

Watcher.prototype.teardown = function teardown () {var this$1 = this;if (this.active) {// remove self from vm's watcher list// this is a somewhat expensive operation so we skip it// if the vm is being destroyed.if (!this.vm._isBeingDestroyed) {remove(this.vm._watchers, this);}var i = this.deps.length;while (i--) {this$1.deps[i].removeSub(this$1);}this.active = false;} };

看到這里,我們知道,盡管被destroy,_watcher還是那個_watcher(此時,如果調用$mount,就不是了)。什么意思呢?就是說每個屬性值還是被放在它們各自的watcher中被監控著的。只不過,由于這些watcher都從deps里面被退訂了,那么一旦它們的值被更改,將不會調用watcher的update(因為每個watcher的update方法是在dep的notify里面被調用的)。

我們看到update被調用的時候,實際是調用了run方法,也就是說真正的update(this.cb)實在run里面被調用。

在run里面,先判斷active,如果是false就不更新視圖(不再響應式了)

Watcher.prototype.update = function update () {/* istanbul ignore else */if (this.lazy) {this.dirty = true;} else if (this.sync) {this.run();} else {queueWatcher(this);} };// Watcher.prototype.run = function run () {if (this.active) {var value = this.get();if (value !== this.value ||// Deep watchers and watchers on Object/Arrays should fire even// when the value is the same, because the value may// have mutated.isObject(value) ||this.deep) {// set new valuevar oldValue = this.value;this.value = value;/..../{this.cb.call(this.vm, value, oldValue);}}} };

好了,當我們再次調用app.$mount(),其實我們此時是重新編譯了一遍節點。此時經歷了這么個過程: beforeMount => beforeUpdate => updated => mounted

查看源碼,我們發現$mount方法里面調用了compileToFunctions方法,而compileToFunctions方法里面調用了compile方法,也就是說,此時我們為app.mes屬性,重新new了一個Watcher。

var mount = Vue.prototype.$mount; Vue.prototype.$mount = function (el,hydrating){//.......var ref = compileToFunctions(template, {shouldDecodeNewlines: shouldDecodeNewlines,shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref,delimiters: options.delimiters,comments: options.comments}, this);//....} //... function compileToFunctions(){//....var compiled = compile(template, options);//... }

如果讀者對以上分析感到疑惑,我們可以測試一下:

在調用destroy之前,我們先聲明一個變量p來保持對此時的watcher對象的引用(由于jvm是根據對對象的持有,來決定是否從內存中刪除此對象。所以這個舊的watcher不會被刪除)

// teardown之前 p=app._watcher.deps[0].subs[0]; // teardown之后,又調用$mount() pp = app._watcher.deps[0].subs[0];// 比較 p === pp //輸出false,說明這個watcher是新new出來的

-輕松掌握-vue-實例的生命周期/

-Vue2.0 探索之路——生命周期和鉤子函數的一些理解


更多專業前端知識,請上 【猿2048】www.mk2048.com

總結

以上是生活随笔為你收集整理的Vue生命周期详解 对应代码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。