前言
在使用vue開發過程中經常會接觸到生命週期的問題,但對於每個鉤子函式都做了什麼,應用場景比較模糊,希望通過這次梳理讓自己清楚一些。初次寫文章,有不對的地方還望各位多多指正!
1. vue例項化過程
從vue例項化開始分析,我們通過new Vue來例項化來檢視一下原始碼 在 src/core/instance/init.js 中定義 使用vscode的小夥伴推薦使用Search node_modules外掛查詢node_modules中的外掛方便多了,媽媽再也不用擔心我迷路了
Vue.prototype._init = function (options?: Object) {
// ... 省略程式碼
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`vue ${vm._name} init`, startTag, endTag)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
複製程式碼
Vue 初始化主要就幹了幾件事情,合併配置,初始化生命週期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等,vue 把不同的功能邏輯拆成一些單獨的函式執行。
我們關注到,在這個過程中插入鉤子函式,提供給開發者呼叫的機會。在初始化的最後,檢測到如果有 el 屬性,則呼叫 vm.$mount 方法掛載 vm,掛載的目標就是把模板渲染成最終的 DOM。
2.生命週期鉤子
- 生命週期鉤子自動繫結this到例項上,因此你可以通過this.操作訪問到資料和方法。注意不能使用箭頭函式例如下方程式碼,因為箭頭函式繫結外層的this會一直往上找。
created:()=>{// ...程式碼}
複製程式碼
- 下面用在各個生命週期中列印下el,data,dom節點
export default {
name: 'App',
data() {
return {
title: '標題'
}
},
methods: {
onDestoryClick() {
this.$destroy()
}
},
beforeCreate() {
console.log(
`\n\nbeforeCreate打頭\n$el :${this.$el}\n$data :${JSON.stringify(
this.$data
)}\n$refs.head :${JSON.stringify(
this.$refs.head
)}\nbeforeCreate結尾\n\n`
)
console.log(this.$vnode)
},
created() {
console.log(
`\n\ncreated打頭\n$el :${this.$el}\n$data :${JSON.stringify(
this.$data
)}\n$refs.head :${JSON.stringify(this.$refs.head)}\ncreated結尾\n\n`
)
console.log(this.$vnode)
},
beforeMount() {
console.log(
`\n\nbeforeMount打頭\n$el :${this.$el}\n$data :${JSON.stringify(
this.$data
)}\n$refs.head :${JSON.stringify(this.$refs.head)}\nbeforeMount結尾\n\n`
)
console.log(this.$vnode)
},
mounted() {
console.log(
`\n\nmounted打頭\n$el :${this.$el}\n$data :${JSON.stringify(
this.$data
)}\n$refs.head :${JSON.stringify(this.$refs.head)}\nmounted結尾\n\n`
)
console.log(this.$vnode)
}
}
複製程式碼
可以發現
-
beforeCreate中拿不到任何資料,它在例項初始化之後,資料觀測 (data observer) 和 event/watcher 事件配置之前被呼叫。
-
created中已經可以拿到data中的資料了,但是dom還沒有掛載。會判斷有無el,如果沒有el則停止後面的模板掛載。
在例項建立完成後被立即呼叫。在這一步,例項已完成以下的配置:資料觀測 (data observer),屬性和方法的運算,watch/event 事件回撥。
使用場景:ajax請求和頁面初始化
-
beforeMount 和 created 拿到的資料相同 在掛載開始之前被呼叫:相關的 render 函式首次被呼叫。
-
mounted中el被建立dom已經更新,vue例項物件中有template引數選項,則將其作為模板編譯成render函式,編譯優先順序render函式選項 > template選項
使用場景:常用於獲取VNode資訊和操作,ajax請求
注意 mounted 不會承諾所有的子元件也都一起被掛載。如果你希望等到整個檢視都渲染完畢,可以用 vm.$nextTick 替換掉 mounted
-
由於beforeUpdate和updated使用的比較少,一般用計算屬性和watch代替所以在此不在說明
-
destroyed Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。
客戶端渲染過程
- 處理 HTML 標記並構建 DOM 樹。
- 處理 CSS 標記並構建 CSSOM 樹。
- 將 DOM 與 CSSOM 合併成一個渲染樹。
- 根據渲染樹來佈局,以計算每個節點的幾何資訊。
- 將各個節點繪製到螢幕上。