Vue LifeCycle

MVVM

MVVM是Model-View-ViewModel的縮寫

  • Model代表數(shù)據(jù)模型,可在Model中定義數(shù)據(jù)修改等操作的業(yè)務(wù)邏輯。
  • View代表UI界面組件,負(fù)責(zé)將數(shù)據(jù)模型Model轉(zhuǎn)化為UI進(jìn)行展示。
  • ViewModel表示監(jiān)聽模型中數(shù)據(jù)的改變并控制視圖的行為,用于處理用戶交互。簡(jiǎn)單來(lái)說(shuō),ViewModel是一個(gè)同步View和Model的對(duì)象,用來(lái)連接View和Model。
MVVM

MVVM架構(gòu)中View和Model之間并沒有直接的聯(lián)系,而是通過(guò)ViewModel進(jìn)行交互。

Model和ViewModel之間的交互是雙向的,因此View上數(shù)據(jù)的變化會(huì)同步到Model中,而Model數(shù)據(jù)的變化也會(huì)立即反映到View上。

ViewModel通過(guò)雙向數(shù)據(jù)綁定將View層和Model層連接起來(lái),而View和Model之間的同步工作完全是自動(dòng)的,無(wú)需人為干預(yù)。開發(fā)者只需要關(guān)注業(yè)務(wù)邏輯,無(wú)需手動(dòng)操作DOM,無(wú)需關(guān)注數(shù)據(jù)狀態(tài)的同步問題,復(fù)雜的數(shù)據(jù)狀態(tài)維護(hù)完全由MVVM來(lái)統(tǒng)一管理。

Vue雙向數(shù)據(jù)綁定

Vue最顯著的兩個(gè)核心是數(shù)據(jù)驅(qū)動(dòng)和組件系統(tǒng)

Vue實(shí)現(xiàn)數(shù)據(jù)雙向綁定的原理是Object.defineProperty()方法,即采用數(shù)據(jù)劫持并結(jié)合發(fā)布者-訂閱者模式,通過(guò)Object.defineProperty()方法來(lái)劫持屬性的setter/getter。當(dāng)數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)對(duì)應(yīng)監(jiān)聽回調(diào)。當(dāng)將一個(gè)普通的JavaScript對(duì)象傳遞給Vue實(shí)例作為data選項(xiàng)時(shí),Vue會(huì)遍歷其屬性,并使用Object.defineProperty()方法將他們轉(zhuǎn)換為getter/setter。用戶是看不到setter/getter方法,但在內(nèi)部它們會(huì)讓Vue追蹤依賴,在屬性被訪問和修改時(shí)會(huì)通知其變化。

數(shù)據(jù)綁定

Vue的數(shù)據(jù)雙向綁定會(huì)見MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile、Watcher三者,通過(guò)Observer來(lái)監(jiān)聽自己Model數(shù)據(jù)的變化,通過(guò)Compile解析編譯模板指令,最終利用Watcher搭建起Observer和Compile之間的通信橋梁,以達(dá)到數(shù)據(jù)變化視圖更新,視圖交互變化數(shù)據(jù)模型Model變更的雙向綁定效果。

Vue生命周期

Vue實(shí)例都具有一個(gè)完整的生命周期,從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載DOM、渲染更新渲染、卸載等一系列的過(guò)程。簡(jiǎn)單來(lái)說(shuō),就是Vue實(shí)例從創(chuàng)建到銷毀的過(guò)程。

為什么會(huì)存在Vue的生命周期呢?Vue生命周期的作用是因?yàn)槠渖芷趦?nèi)存在多個(gè)事件鉤子,用以控制整個(gè)Vue實(shí)例的過(guò)程時(shí)更容易形成清晰的邏輯。Vue實(shí)例生命周期中,提供了一系列事件,使其在事件觸發(fā)時(shí)注冊(cè)JS方法,以使用自己注冊(cè)的JS方法控制整個(gè)大局,在這些事件響應(yīng)方法中this直接指向的是Vue實(shí)例。

Vue生命周期可分為4大階段8小階段,分別是

  • 創(chuàng)建前后beforeCreate/created
  • 載入前后beforeMount/mounted
  • 更新前后beforeUpdate/updated
  • 銷毀前后beforeDestroy/destroyed

當(dāng)?shù)谝淮雾?yè)面加載時(shí)會(huì)觸發(fā)beforeCreatecreatedbeforeMountmounted鉤子函數(shù),DOM渲染則在mounted中就已經(jīng)完成了。

Vue實(shí)例生命周期鉤子

每個(gè)Vue實(shí)例在被創(chuàng)建時(shí)都需經(jīng)過(guò)一系列初始化過(guò)程,例如,設(shè)置數(shù)據(jù)監(jiān)聽、編譯模板、將實(shí)例掛在到DOM并在數(shù)據(jù)變化時(shí)更新DOM等。同時(shí)在此過(guò)程中也會(huì)運(yùn)行一些稱為生命周期鉤子的函數(shù),以方便用戶在不同階段添加代碼。

鉤子 描述
beforeCreate 組件實(shí)例剛剛被創(chuàng)建,組件屬性計(jì)算之前。
created 用來(lái)在實(shí)例創(chuàng)建之后執(zhí)行代碼,組件實(shí)例創(chuàng)建完成,屬性已綁定,DOOM未生成,$el屬性不存在。
beforeMount 模板編譯或掛載之前
mounted 模板編譯或掛載之后,此時(shí)并不能保證組件已在document中。
beforeUpdate 組件更新之前
updated 組件更新之后
beforeDestroy 組件銷毀前調(diào)用
destroyed 組件銷毀后調(diào)用

生命周期鉤子是在Vue對(duì)象生命周期的某個(gè)階段執(zhí)行的已定義的方法,從初始化到被銷毀,對(duì)象都會(huì)遵循不同的生命階段。

Vue實(shí)例生命周期
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>vue</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-model="input.msg" ref="msg" />
        <button @click="onHandle">更新</button>
    </div>
    <script>
        const vm = new Vue({
            //DOM
            el:"#app",
            //數(shù)據(jù)
            data(){
                return {
                    input:{msg:"hello world"}
                };
            },
            //生命周期鉤子函數(shù)
            beforeCreate(){
                console.log(1, "before create", this.$el, this.input);
            },
            created(){
                console.log(2, "created", this.$el, this.input);
            },
            beforeMount(){
                this.$set(this.input, "msg", "helo");
                console.log(3, "before mount", this.$el, this.input);
            },
            mounted(){
                console.log(4, "mounted", this.$el, this.input, this.$refs.msg);
            },
            beforeUpdate(){
                console.log(5, "before update", this.$el, this.input);
            },
            updated(){
                console.log(6, "updated", this.$el, this.input);
            },
            beforeDestroy(){
                console.log(7, "before destroy", this.$el, this.input);
            },
            destroyed(){
                console.log(8, "destroyed", this.$el, this.input);
            },
            //
            methods:{
                onHandle(){
                    this.input.msg = "hi";
                }
            }
        });
    </script>
</body>
</html>

Vue內(nèi)置方法屬性和生命周期的運(yùn)行順序

運(yùn)行順序 屬性方法
1 props
2 methods
3 data
4 computed
5 watch

創(chuàng)建期間的生命周期函數(shù)

創(chuàng)建前beforeCreate

  • 組件創(chuàng)建會(huì)執(zhí)行生命周期函數(shù)beforeCreate,可在當(dāng)前生命周期中創(chuàng)建一個(gè)Loading,當(dāng)頁(yè)面加載完成后再移除Loading。
  • beforeCreate在當(dāng)前生命周期函數(shù)中是訪問不到其他生命周期函數(shù)以及data屬性的。

Vue實(shí)例化后會(huì)創(chuàng)建一個(gè)Vue類的對(duì)象用來(lái)處理DOM元素,這個(gè)對(duì)象的生命周期可以通過(guò)beforeCreate鉤子函數(shù)來(lái)訪問。

Vue實(shí)例剛從內(nèi)存中被創(chuàng)建出來(lái),此時(shí)還沒有初始化好datamethods屬性。

在Vue實(shí)例初始化之后,數(shù)據(jù)觀測(cè)data observerevent/watcher事件配置之前被調(diào)用。

beforeCreate實(shí)例創(chuàng)建前會(huì)遍歷data對(duì)象下所有屬性并將其轉(zhuǎn)化為setter/getter,也就是為其添加一個(gè)被觀察者,后續(xù)添加新屬性時(shí)視圖不用更新即可使用,后續(xù)添加的屬性并不會(huì)放到觀察者對(duì)象中,此時(shí)數(shù)據(jù)并沒有和模板建立聯(lián)系,因此不能操作該屬性。如果要在實(shí)例掛在完成后使添加的屬性觸發(fā)視圖的更新,可使用$set方法,$set方法會(huì)向被觀察者對(duì)象中新增自定義的屬性。

創(chuàng)建后created

  • 當(dāng)created生命周期函數(shù)執(zhí)行時(shí)會(huì)將data和methods身上的屬性和方法添加到vm實(shí)例上
  • created執(zhí)行時(shí)會(huì)遍歷data的屬性并為屬性添加setter和getter方法
  • 可以在created生命周期函數(shù)中發(fā)起AJAX數(shù)據(jù)請(qǐng)求

created階段,對(duì)象及其事件已經(jīng)完全初始化, created是訪問此階段并編寫代碼的鉤子,簡(jiǎn)單來(lái)說(shuō),此階段是具有默認(rèn)特性的對(duì)象。

Vue實(shí)例已經(jīng)創(chuàng)建完成后被調(diào)用,在這一步Vue實(shí)例已經(jīng)完成配置:數(shù)據(jù)觀測(cè)(data observer)、屬性和方法的運(yùn)算(computed)、watch/event事件回調(diào)。然而,掛載階段還沒開始,$el屬性目前尚不可見。

在模板渲染成HTML前調(diào)用,即通常初始化某些屬性值,然后再渲染成視圖。

Vue實(shí)例已經(jīng)在內(nèi)存中創(chuàng)建完成,此時(shí)datamethods已經(jīng)創(chuàng)建完成,此時(shí)還未開始編譯模板。

created階段Vue實(shí)例已經(jīng)被創(chuàng)建完畢,屬性已經(jīng)綁定,屬性是可以操作的。但DOM還不存在,$el屬性也還不可以操作。此時(shí)也可以使用axios請(qǐng)求,但頁(yè)面還未被渲染出來(lái),若請(qǐng)求時(shí)間過(guò)長(zhǎng)則會(huì)出現(xiàn)長(zhǎng)時(shí)間的白屏的現(xiàn)象,因此推薦添加Loading界面。

掛載前 beforeMount

  • 生命周期函數(shù)beforeMount可以對(duì)data中的數(shù)據(jù)做最后修改
  • beforeMount生命周期函數(shù)中添加的屬性沒有settergetter方法,若需要?jiǎng)t需使用$set方法。
  • beforeMount生命周期函數(shù)中模板和數(shù)據(jù)未進(jìn)行結(jié)合

beforeMount鉤子調(diào)用階段會(huì)檢查是否具有模板用于要在DOM中呈現(xiàn)的對(duì)象,若沒有模板則將定義元素的外部HTML視為模板。

beforeMount在掛載開始之前被調(diào)用,相關(guān)的render函數(shù)首次被調(diào)用。beforeMount階段已經(jīng)完成了模板的編譯但還未掛在到頁(yè)面中。

掛載后mounted

  • mounted掛載后數(shù)據(jù)和模板會(huì)進(jìn)行結(jié)合并生成真正的DOM結(jié)構(gòu)
  • mounted函數(shù)中可訪問到真實(shí)的DOM結(jié)構(gòu)
  • mounted函數(shù)中可用于插件實(shí)例化

一旦模板準(zhǔn)備就緒,就會(huì)將數(shù)據(jù)放入模板并創(chuàng)建可呈現(xiàn)元素。使用新數(shù)據(jù)填充元素替換DOM元素。mounted鉤子表示DOM已準(zhǔn)備就緒并放置到頁(yè)面中。

el被新創(chuàng)建的vm.$el替換,并掛載到實(shí)例上去之后調(diào)用該鉤子。

在模板渲染成HTML后調(diào)用,通常是初始化頁(yè)面完成后,再對(duì)HTML的DOM節(jié)點(diǎn)進(jìn)行一些需要的操作。

mounted階段此時(shí)已經(jīng)將編譯好的模板掛載到了頁(yè)面指定的容器中顯示。

運(yùn)行期間的生命周期函數(shù)

更新前beforeUpdate

  • beforeUpdate會(huì)多次執(zhí)行,當(dāng)數(shù)據(jù)更新前會(huì)執(zhí)行。
  • beforeUpdate更新前數(shù)據(jù)還未和模板結(jié)合,可在此函數(shù)中做更新數(shù)據(jù)的最后修改。

當(dāng)外部事件或用戶輸入時(shí),beforeUpdate鉤子在反映原始DOM元素的更改之前被觸發(fā),此階段表示更改已經(jīng)完成,但尚未準(zhǔn)備好更新DOM。

數(shù)據(jù)更新時(shí)調(diào)用,發(fā)生在虛擬DOM重新渲染和打補(bǔ)丁之前。可以在狗子中進(jìn)一步地更改狀態(tài),這不會(huì)出發(fā)附加的重渲染過(guò)程。

狀態(tài)更新之前執(zhí)行beforeUpdate鉤子函數(shù),此時(shí)data中的狀態(tài)值是最新的,但界面上顯示的數(shù)據(jù)還是舊的,因?yàn)榇藭r(shí)還沒有開始重新渲染DOM節(jié)點(diǎn)。

更新后updated

  • updated函數(shù)是更新的數(shù)據(jù)和模板進(jìn)行組合的位置
  • 可在updated函數(shù)中獲取到數(shù)據(jù)更新后最新的DOM結(jié)構(gòu)
  • 可在updated函數(shù)中做插件的實(shí)例化,但需添加判斷條件否則會(huì)非常消耗性能。

updated鉤子表示在DOM中程序的更改,通過(guò)實(shí)際更新DOM對(duì)象并觸發(fā)updated方法,屏幕上的變化才得以呈現(xiàn)。

由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁,在這之后會(huì)調(diào)用該鉤子。

當(dāng)這個(gè)鉤子被調(diào)用時(shí),組件DOM已經(jīng)更新,所以現(xiàn)在可以執(zhí)行依賴于DOM的操作。然而大多數(shù)情況下,應(yīng)該避免在此期間更改狀態(tài),因?yàn)檫@可能會(huì)導(dǎo)致更新無(wú)限循環(huán)。

updated函數(shù)在Vue實(shí)例更新完畢后調(diào)用,此時(shí)data中的狀態(tài)值和界面上顯示的數(shù)據(jù)都已經(jīng)完成了更新,界面已經(jīng)被重新渲染好了。

銷毀期間的生命周期函數(shù)

銷毀前beforeDestroy

  • beforeDestroy函數(shù)中可訪問到真實(shí)的DOM結(jié)構(gòu),可在當(dāng)前生命周期函數(shù)中做事件的解綁、監(jiān)聽移除等操作。

當(dāng)Vue對(duì)象被破壞并從內(nèi)存中釋放之前beforeDestroy鉤子被觸發(fā)

Vue實(shí)例銷毀之前調(diào)用,在這一步中Vue實(shí)例仍然完全可用。

beforeDestroy鉤子函數(shù)在Vue實(shí)力銷毀之前調(diào)用,此時(shí)Vue實(shí)力仍然完全可用。

銷毀后destroyed

  • destroyed函數(shù)執(zhí)行時(shí)會(huì)將vm和模板之間的關(guān)聯(lián)斷開
  • destroyed函數(shù)中無(wú)法通過(guò)ref訪問到真實(shí)DOM結(jié)構(gòu)

destroyed鉤子被成功運(yùn)行銷毀對(duì)象上調(diào)用,對(duì)象停止并從內(nèi)存中刪除。

Vue實(shí)例銷毀后調(diào)用,調(diào)用后Vue實(shí)例指示的所有東西都會(huì)解綁定,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀。該鉤子在服務(wù)器端渲染期間不會(huì)被調(diào)用。

destroyed鉤子函數(shù)在Vue實(shí)例銷毀后調(diào)用,調(diào)用后Vue實(shí)例指向會(huì)解除綁定,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀。

created 與 mounted

  • beforeCreated時(shí)eldata并未初始化
  • created階段完成data數(shù)據(jù)的初始化,此時(shí)el還不存在。
  • beforeMount階段完成了eldata的初始化
  • mounted階段完成掛載。

created在模板渲染成HTML前調(diào)用,即通常初始化某些屬性值,然后再渲染成視圖。

mounted在模板渲染成HTML后調(diào)用,通常是初始化頁(yè)面完成后再對(duì)HTML的DOM節(jié)點(diǎn)進(jìn)行一些需要的操作。

通常created使用的次數(shù)多,而mounted通常是在一些插件的使用或組件的使用中進(jìn)行操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,772評(píng)論 3 422
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,960評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,350評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,549評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,104評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,914評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,089評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,340評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評(píng)論 1 289
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,834評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,106評(píng)論 2 375