深入vue生命周期

深入vue生命周期

來自專欄 Web前端開發工程師成長營1 人贊了文章

這篇博客將會從下面四個常見的應用詮釋組件的生命周期,以及各個生命周期應該幹什麼事

  • 單組件的生命周期
  • 父子組件的生命周期
  • 兄弟組件的生命周期
  • 宏mixin的生命周期

生命周期:Vue 實例從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、卸載等一系列過程,我們稱這是 Vue 的生命周期,各個階段有相對應的事件鉤子

1. 生命周期鉤子函數

下面這張圖是vue生命周期各個階段的執行情況:

注意:

  • created階段的ajax請求與mounted請求的區別:前者頁面視圖未出現,如果請求信息過多,頁面會長時間處於白屏狀態
  • mounted 不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染

完畢,可以用 vm.$nextTick

vue2.0之後主動調用$destroy()不會移除dom節點,作者不推薦直接destroy這種做法,如果實在需要這樣用可以在這個生命周期鉤子中手動移除dom節點

2. 單個組件的生命周期

現根據實際代碼執行情況分析:

<template>

<div>

<h3>單組件</h3>

<el-button @click="dataVar += 1">更新 {{dataVar}}</el-button>

<el-button @click="handleDestroy">銷毀</el-button>

</div>

</template>

export default {

data() {

return {

dataVar: 1

}

},

beforeCreate() {

this.compName = single

console.log(`--${this.compName}--beforeCreate`)

},

created() {

console.log(`--${this.compName}--created`)

},

beforeMount() {

console.log(`--${this.compName}--beforeMount`)

},

mounted() {

console.log(`--${this.compName}--mounted`)

},

beforeUpdate() {

console.log(`--${this.compName}--beforeUpdate`)

},

updated() {

console.log(`--${this.compName}--updated`)

},

beforeDestroy() {

console.log(`--${this.compName}--beforeDestroy`)

},

destroyed() {

console.log(`--${this.compName}--destroyed`)

},

methods: {

handleDestroy() {

this.$destroy()

}

}

}

初始化組件時,列印:

當data中的值變化時,列印:

當組件銷毀時,列印:

從列印結果可以看出:

  • 初始化組件時,僅執行了beforeCreate/Created/beforeMount/mounted四個鉤子函數
  • 當改變data中定義的變數(響應式變數)時,會執行beforeUpdate/updated鉤子函數
  • 當切換組件(當前組件未緩存)時,會執行beforeDestory/destroyed鉤子函數
  • 初始化和銷毀時的生命鉤子函數均只會執行一次,beforeUpdate/updated可多次執行

3. 父子組件的生命周期

將單組件作為基礎組件(由於props在beforeCreate()中未初始化),需要做如下更改:

props: {

compName: {

type: String,

default: single

}

},

beforeCreate() {

// this.compName = single

// console.log(`--${this.compName}--beforeCreate`)

console.log(` --data未初始化--beforeCreate`)

},

父組件代碼如下:

<template>

<div class="complex">

<h3>複雜組件</h3>

<lifecycle-single compName="child"></lifecycle-single>

</div>

</template>

const COMPONENT_NAME = complex

import LifecycleSingle from ./LifeCycleSingle

export default {

beforeCreate() {

console.log(`--${COMPONENT_NAME}--beforeCreate`)

},

created() {

console.log(`--${COMPONENT_NAME}--created`)

},

beforeMount() {

console.log(`--${COMPONENT_NAME}--beforeMount`)

},

mounted() {

console.log(`--${COMPONENT_NAME}--mounted`)

},

beforeUpdate() {

console.log(`--${COMPONENT_NAME}--beforeUpdate`)

},

updated() {

console.log(`--${COMPONENT_NAME}--updated`)

},

beforeDestroy() {

console.log(`--${COMPONENT_NAME}--beforeDestroy`)

},

destroyed() {

console.log(`--${COMPONENT_NAME}--destroyed`)

},

components: {

LifecycleSingle

}

}

初始化組件時,列印:

當子組件data中的值變化時,列印:

當父組件data中的值變化時,列印:

當props改變時,列印:

當子組件銷毀時,列印:

當父組件銷毀時,列印:

從列印結果可以看出:

  • 僅當子組件完成掛載後,父組件才會掛載
  • 當子組件完成掛載後,父組件會主動執行一次beforeUpdate/updated鉤子函數(僅首次)
  • 父子組件在data變化中是分別監控的,但是在更新props中的數據是關聯的(可實踐)
  • 銷毀父組件時,先將子組件銷毀後才會銷毀父組件

4. 兄弟組件的生命周期

在上面的基礎上,複雜組件做如下更改

<template>

<div class="complex">

<h3>複雜組件</h3>

<lifecycle-single compName="cihld1"></lifecycle-single>

<lifecycle-single compName="child2"></lifecycle-single>

<el-button @click="dataVar += 1">complex更新 {{dataVar}}</el-button>

<el-button @click="handleDestroy">complex銷毀</el-button>

</div>

</template>

初始化組件時,列印:

當child1更新和銷毀時,列印:

當child2更新和銷毀時,列印:

當父組件銷毀時,列印

從列印結果可以看出:

  • 組件的初始化(mounted之前)分開進行,掛載是從上到下依次進行
  • 當沒有數據關聯時,兄弟組件之間的更新和銷毀是互不關聯的

5. 宏mixin的生命周期

在上面的基礎上,添加一個mixin.js文件,內容如下:

const COMPONENT_NAME = lifecycleMixin

export default {

name: COMPONENT_NAME,

beforeCreate() {

console.log(`--${COMPONENT_NAME}--beforeCreate`)

},

created() {

console.log(`--${COMPONENT_NAME}--created`)

},

beforeMount() {

console.log(`--${COMPONENT_NAME}--beforeMount`)

},

mounted() {

console.log(`--${COMPONENT_NAME}--mounted`)

},

beforeUpdate() {

console.log(`--${COMPONENT_NAME}--beforeUpdate`)

},

updated() {

console.log(`--${COMPONENT_NAME}--updated`)

},

beforeDestroy() {

console.log(`--${COMPONENT_NAME}--beforeDestroy`)

},

destroyed() {

console.log(`--${COMPONENT_NAME}--destroyed`)

}

}

同樣的,複雜組件做如下更改:

import lifecycleMixin from ./mixin

export default {

mixins: [lifecycleMixin],

// ...

}

組件初始化時,列印:

組件銷毀時,列印:

從列印結果可以看出:

mixin中的生命周期與引入該組件的生命周期是僅僅關聯的,且mixin的生命周期優先執行

參考:

  • vue官網教程
  • vue官網API
  • Vue2.0生命周期(組件鉤子函數與路由守衛)

作者:同夢奇緣

segmentfault.com/a/1190


推薦閱讀:

TAG:Vuejs | 前端入門 |