有哪些生命周期方法
把所有生命周期打印一遍
import Vue from 'vue'
const app = new Vue({
// el: '#root',
template: '<div>{{text}}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'breforeCreate')
},
created () {
console.log(this, 'created')
},
beforeMount () {
console.log(this, 'beforeMount')
},
mounted () {
console.log(this, 'mounted')
},
beforeUpdate () {
console.log(this, 'beforeUpdate')
},
updated () {
console.log(this, 'updated')
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
app.$mount('#root')
顯示結(jié)果
結(jié)果依次顯示 “breforeCreate” "created" "beforeMount" "mounted",說明在new Vue()時,這四個方法執(zhí)行了。
breforeMount 和 mounted
如果把el:'#root'注釋掉,就只顯示“breforeCreate” "created" ,因為mount的作用就是把vue組件生成的html內(nèi)容,掛載到html節(jié)點上,所以當(dāng)我們沒有指定el:'#root'或通過$mount進(jìn)行,是不會掛載到html節(jié)點上的。
breforeCreate 和 created
而 breforeCreate created 在初始化階段就執(zhí)行了。
beforeUpdate 和 updated
數(shù)據(jù)更新時,才會執(zhí)行。
例如,每一秒鐘更改數(shù)據(jù),相應(yīng)的每秒都會執(zhí)行這兩個生命周期
setInterval(() => {
app.text = app.text += 1
}, 1000)
beforeDestroy 和 destroyed
vue實例銷毀時執(zhí)行。
例如,設(shè)置一秒鐘后銷毀,控制臺就會顯示 "beforeDestroy" 和 "destroyed"
setTimeout(() => {
app.$destroy()
}, 1000)
activated 和 deactivated
和vue中一個原生的組件 keep-alive有關(guān)系。
分別打印出不同周期對應(yīng)的$el
beforeCreate () {
console.log(this.$el, 'breforeCreate')
},
created () {
console.log(this.$el, 'created')
},
beforeMount () {
console.log(this.$el, 'beforeMount')
},
mounted () {
console.log(this.$el, 'mounted')
},
顯示結(jié)果
undefined "beforeCreate"
undefined "created"
<div id="root"></div> "beforeMount"
<div>0</div> "mounted"
可以看到
beforeCreate 和 created 的 $el 是undefined,所以 beforeCreate 和 created 階段是不能進(jìn)行dom操作的,因為拿不到 dom 節(jié)點。
brforeMount 時,$el變成了我們寫在 html 中 div 節(jié)點。
mounted 時, $el變成了 template 中的html,說明覆蓋了html原來的 div 節(jié)點。
mounted之后,我們調(diào)用的所有生命周期方法,拿到的節(jié)點,都是渲染之后的節(jié)點。
所以一般
- 做 dom 相關(guān)操作會在 mounted 階段
- 數(shù)據(jù)相關(guān)操作,可以在 created 或 mounted 階段
生命周期的調(diào)用順序
beforeCreate created beforeMount mounted 都是一次性的,組件只會調(diào)用一次。
beforeMount mounted 在服務(wù)端渲染,是不會被調(diào)用的,服務(wù)端渲染過程中,只會調(diào)用 beforeCreate created,因為 mount 是和 dom 操作相關(guān)的,服務(wù)端根本沒有 dom 執(zhí)行的環(huán)境, 所以不會有。
當(dāng)數(shù)據(jù)發(fā)生變化時,beforeUpdate 和 updated 會調(diào)用。
當(dāng)組件銷毀時,beforeDestroy 和 destroyed 會調(diào)用。
聲明周期中 VUE 實例有哪些區(qū)別
在不同的生命周期階段,this.$el是不同的,而在 mounted之后,一般不會改動 this.$el,而是圍繞階段做某些操作,要盡量避免 this.$el的變動,它會導(dǎo)致一些 vue 錯誤。
理解生命周期就是理解一張圖

- init,new Vue() 先執(zhí)行 init 操作,這個操作是默認(rèn)執(zhí)行的。
- init Events $ Lifecycle,調(diào)用 beforeCreate,所以此時,事件OK,但reactive不OK,所以這個階段不要修改數(shù)據(jù) data 中的數(shù)據(jù)。
- init injections $ reactivity,調(diào)用 created ,ajax請求獲取數(shù)據(jù)賦值,最早在 created 階段做。
- 判斷 Has "el" option
- 如果有,執(zhí)行下一步。
- 如果沒有,等我們調(diào)用
vm.$mounted(el)。
- 判斷 Has "template" options
- 如果有,把 template 解析生一個 render 函數(shù)。render 函數(shù)會用 template 中的 html 去覆蓋 html 中的 div 標(biāo)簽。在使用
.vue文件進(jìn)行開發(fā)的過程中,是沒有 template 的,我們在.vue文件中寫的 template 都經(jīng)過了 vue-loader 處理,直接變成了 render 函數(shù),放在vue-loader 解析過的文件中;這樣做的好處,把 template 解析成 render 函數(shù),比較耗時,vue-loader 處理后,我們在頁面上執(zhí)行代碼時,效率會變高。 - 如果沒有,Compile el's outerHTML as template
- 如果有,把 template 解析生一個 render 函數(shù)。render 函數(shù)會用 template 中的 html 去覆蓋 html 中的 div 標(biāo)簽。在使用
- 有了 render 函數(shù)之后
- beforeMount 執(zhí)行
- 執(zhí)行 render 函數(shù)
- Create vm.$el and replace "el" with it
- 執(zhí)行 render 函數(shù)之后
- mounted 執(zhí)行
- mounted之后,實例創(chuàng)建完成,后續(xù)過程,都是通過外部觸發(fā)進(jìn)行的。
- 當(dāng)數(shù)據(jù)變化時
- beforeUpdate 執(zhí)行
- Virtual DOM re-render and patch
- updated 執(zhí)行
- 當(dāng)組件銷毀時
- beforeDestroy 執(zhí)行
- Teardown watchers,child comonents and event listeners
- destroyed 執(zhí)行
render 函數(shù)
直接使用 render 函數(shù)和使用 template 一樣的。
import Vue from 'vue'
const app = new Vue({
// template: '<div>{{text}}</div>',
data: {
text: 0
},
render (h) {
return h('div', {}, this.text) // 參數(shù)1,創(chuàng)建的標(biāo)簽;參數(shù)2,對象配置;參數(shù)3,標(biāo)簽內(nèi)容
},
})
app.$mount('#root')
render 函數(shù)執(zhí)行時機(jī)
render (h) {
console.log('render function invoked')
return h('div', {}, this.text)
},
控制臺結(jié)果
undefined "beforeCreate"
undefined "created"
<div id="root"></div> "beforeMount"
render function invoked
<div>0</div> "mounted"
在beforeMount 和 mounted 之間執(zhí)行的
renderError 方法
renderError 方法,只有在開發(fā)時,才會被調(diào)用,正式打包上線時,不會被調(diào)用。幫助我們調(diào)試 render 中的錯誤。renderError 方法,只有在本組件 render 出現(xiàn)錯誤時,才會被調(diào)用;如果是子組件報錯,是不會被捕獲到的。
當(dāng) render 函數(shù)報錯時,renderError 方法會執(zhí)行。
render (h) {
throw new TypeError('render error')
// console.log('render function invoked')
// return h('div', {}, this.text)
},
renderError (h, err) {
return h('div', {}, err.stack)
}
errorCaptured 方法
可以用在正式開發(fā)環(huán)境中,幫助我們搜集線上的錯誤。如果在根組件使用這個方法,而根組件的子組件報的任何錯誤都可捕捉到,除非子組件把向上冒泡停止掉。
errorCaptured 方法使用與 renderError 相似,唯一的區(qū)別是:errorCaptured 會向上冒泡,并且正式環(huán)境可以使用。
總結(jié)
生命周期的執(zhí)行順序,調(diào)用時機(jī),不同時機(jī)進(jìn)行哪些操作,不同生命周期this.$el的區(qū)別。