在以前的 Vue 學習中,咱們在使用 Vue 時,都會建立一個 Vue 的實例,而每一個 Vue 實例在被建立時都要通過一系列的初始化過程。例如,須要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。在這個過程當中,Vue 會運行一些生命週期鉤子函數,而咱們則能夠在鉤子函數中編寫一些自定義方法,用以在 Vue 的整個生命週期中某些階段實現咱們特殊需求。那麼,本章,咱們就來了解 Vue 實例的生命週期鉤子函數。html
學習系列目錄地址:http://www.javashuo.com/article/p-bzzucmub-ba.htmlvue
倉儲地址:https://github.com/Lanesra712/VueTrial/blob/master/Chapter01-Rookie/hocks.htmlgit
在咱們使用 Vue 的時候,都會先建立一個 Vue 實例,這個實例不只是咱們掛載 Vue 框架的入口,也是 MVVM 思想中的 VM(ViewModel)。在咱們使用 Vue 的整個過程當中,歸根結底都是在對這個 Vue 實例進行操做。所以,只有當咱們瞭解 Vue 實例的生命週期以後,才能夠更好的實現咱們的業務邏輯。github
在 Vue 官網的這張生命週期圖示中,咱們能夠看到整個生命週期中包含了8個鉤子函數:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。從字面意思咱們就能夠清楚的看出來,這8個鉤子函數兩個一組,分別對應於 Vue 實例的建立、掛載、更新、銷燬,接下來,咱們就根據這四個階段,解釋 Vue 實例各個階段中的鉤子函數的做用。segmentfault
在咱們經過 new Vue() 建立了一個 Vue 實例以後,會執行 init 方法,此時只會初始化 Vue 實例所包含的一些默認的事件與生命週期函數,在這個實例還未被徹底建立以前,則會執行咱們的 beforeCreate 鉤子函數。瀏覽器
在下面的例子中,咱們在實例化 Vue 對象時,自定義了一個 message 屬性,同時設定了一個 show 方法,如今咱們來看看當實例並無徹底被建立以前,是否可以獲取到咱們自定義的屬性與方法。app
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeCreate() { console.log(`Vue 實例掛載對象 el:${this.$el}`) console.log(`Vue 實例的 data 對象:${this.$data}`) console.log(`Vue 實例的 message 屬性值:${this.message}`) console.log(`Vue 實例的 methods 對象:${this.$options.methods}`) this.show(); } }) </script>
從瀏覽器的控制檯中咱們能夠看到,此時,Vue 實例中的 data、methods 對象,或是咱們定義的 Vue 實例的掛載點元素,在 beforeCreated 生命週期鉤子函數執行時,都沒有進行了初始化。框架
當 beforeCreated 鉤子函數執行完成後,Vue 實例已經初始化完成,此時將要執行生命週期中的 created 鉤子函數來監聽咱們對於數據的更改或是監聽事件。函數
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, created() { console.log(`Vue 實例掛載對象 el:${this.$el}`) console.log(`Vue 實例的 data 對象:${this.$data}`) console.log(`Vue 實例的 message 屬性值:${this.message}`) console.log(`Vue 實例的 methods 對象:${this.$options.methods}`) this.show(); } }) </script>
從瀏覽器控制檯打印出的信息能夠看出,在執行 created 鉤子函數的過程當中,對於自定義的屬性 message、自定義的方法 show 已經初始化完成,此時,整個 Vue 實例已經初始化完成。可是,對於咱們的 Vue 實例的掛載點元素尚未進行初始化。也就是說,當執行完 created 以後,Vue 實例與 View(視圖層)之間依舊是處於隔離的狀態,初始化完成的 Vue 實例也依舊沒有與 DOM 進行綁定。post
當 Vue 實例執行完 beforeCreated、created 鉤子函數以後,Vue 實例已經初始化完成,而 Vue 實例並無掛載到頁面的 DOM 上。在掛載到頁面 DOM 元素以前,則須要執行 beforeMount 鉤子函數將咱們的實例綁定到模板上進行編譯渲染。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeMount() { console.log(document.getElementById('h3').innerText) } }) </script>
從控制檯輸出的信息能夠看到,當執行到 beforeMount 鉤子函數時,已經將模板編譯完成,可是還沒有掛載到頁面上去。
當把編譯完成的模板掛載到頁面上時,則須要執行 mounted 鉤子函數,在這個階段,用戶就能夠看到已經渲染好的頁面。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, mounted() { console.log(document.getElementById('h3').innerText) } }) </script>
這裏咱們能夠看到,已經能夠獲取到差值表達式的值,即當執行到 mounted 鉤子函數時,頁面已經渲染完成了。
從上面的例子中能夠看出,mounted 是建立 Vue 實例過程當中的最後一個生命週期鉤子函數,當執行完 mounted 鉤子函數以後,實例已經被完成建立好,並已經渲染到頁面中,此時,若是咱們不對實例進行任何的操做的話,Vue 實例則不會執行 新的生命週期鉤子函數。
在執行完了 mounted 鉤子函數以後,Vue 實例實際已經脫離了實例的建立階段,進入實例的運行階段。此時,當咱們對實例的 data 進行修改時,則會觸發 beforeUpdate、updated 這兩個鉤子函數。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeUpdate() { console.log(`頁面上的數據:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 數據:${this.message}`) } }) </script>
咱們能夠看到,當咱們對 data 中的 message 屬性進行修改時,在執行 beforeUpdate 鉤子函數時,頁面上的數據仍是舊的數據,而 data 中 message 屬性已經將值修改爲了最新的值(這裏頁面上顯示的爲修改後的數據則是由於執行了後面的鉤子函數,將修改後的數據同步渲染到了頁面上)。
Vue 做爲一個具備數據雙向綁定特性的框架,當咱們實時修改了頁面元素的值以後,確定但願頁面能夠同步變動數據。而在執行 beforeUpdate 鉤子函數以後,咱們已經在實例中修改了數據,如今只須要從新渲染到頁面就能夠了,這時候,則會執行 updated 鉤子函數。
<div id="app"> <h3 id="h3">{{message}}</h3> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, updated() { console.log(`頁面上的數據:${document.getElementById('h3').innerText}`) console.log(`data 中的 message 數據:${this.message}`) } }) </script>
從控制檯能夠看到,當 updated 鉤子函數執行的時候,頁面和 data 中的數據已經完成了同步,都顯示的是最新的數據。此時,整個頁面數據實時變動的操做也已經完成了。
既然有 Vue 實例的建立,那麼在咱們不須要 Vue 實例的時候就須要將這個實例進行銷燬。而 beforeDestroy 以及 destroyed 鉤子函數則會幫咱們實現這一目的。
<div id="app"> {{message}} </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { show() { console.log('執行了 show 方法'); } }, beforeDestroy() { console.log(`Vue 實例掛載對象 el:${this.$el}`) console.log(`Vue 實例的 data 對象:${this.$data}`) console.log(`Vue 實例的 message 屬性值:${this.message}`) console.log(`Vue 實例的 methods 對象:${this.$options.methods}`) this.show(); }, destroyed() { console.log(`Vue 實例掛載對象 el:${this.$el}`) console.log(`Vue 實例的 data 對象:${this.$data}`) console.log(`Vue 實例的 message 屬性值:${this.message}`) console.log(`Vue 實例的 methods 對象:${this.$options.methods}`) this.show(); } }) </script>
這裏,咱們手動銷燬 Vue 實例,從控制檯的輸出內容能夠看到,在 beforeDestroy 和 destroyed 鉤子函數執行中,咱們依舊能夠獲取到 Vue 實例的相關內容,但是,當咱們選擇更新 message 屬性的值時會發現,此時,頁面上顯示的值並無發生改變。原來,這裏的銷燬並不指代'抹去'這個 Vue 實例,而是表示將 Vue 實例與頁面的 DOM 元素進行'解綁'。
鉤子函數 | 描述 |
---|---|
beforeCreate | Vue 實例進行初始化,此時實例的各個組件尚未進行初始化完成,所以不能訪問到 data、computed、watch、methods 上的方法和數據,同時,Vue 實例的掛載點也沒有進行初始化 |
created | Vue 實例初始化完成,此時能夠訪問 data、computed、watch、methods 上的方法和數據,可是依舊沒有進行 Vue 實例的掛載點初始化 |
beforeMount | 將實例綁定到模板並進行渲染,但並不會將實例掛載到頁面上 |
mounted | 將渲染好的模板綁定到頁面上,此時,Vue 實例已徹底建立好 |
beforeUpdate | 數據變動時調用,在實例數據更改以前執行任何應該發生的自定義邏輯或操做 |
updated | 將 Vue 實例更新完成的數據從新渲染到內存中的虛擬 DOM 上,再將虛擬 DOM 應用到頁面上 |
beforeDestroy | Vue 實例進入銷燬階段,此時實例上的 data、methods、過濾器、指令等等仍是處於可用的狀態,尚未真正執行銷燬的過程(解除與頁面 DOM 元素的綁定) |
destroyed | 實例被銷燬(解除與頁面 DOM 元素的綁定) |