vue生命週期詳解

前言

最近在寫業務的時候,老是會遇到一些和vue的生命週期相關的問題,好比: 你用ajax請求數據,而後將數據props到子組件的時候,由於ajax是異步的,而後會發生沒有數據。而後查找緣由仍是本身對這個東西理解不夠深刻。html

生命週期圖

生命鉤子函數

什麼是生命週期函數?vue

好比:react

mounted: function() {
}

// 或者

mounted() {
}
複製代碼
  • 注意點,Vue的全部生命週期函數都是自動綁定到this的上下文上。因此,你這裏使用箭頭函數的話,就會出現this指向的父級做用域,就會報錯。

錯誤的形式:ajax

mounted:() => {
}
複製代碼

beforeCreate

在實例初始化以後,數據觀測和暴露了一些有用的實例屬性與方法。

實例初始化——new Vue()bash

數據觀測——在vue的響應式系統中加入data對象中全部數據,這邊涉及到vue的雙向綁定,能夠看官方文檔上的這篇深度響應式原理 深度響應式原理app

暴露屬性和方法——就是vue實例自帶的一些屬性和方法,咱們能夠看一個官網的例子,例子中帶$的屬性和方法就是vue實例自帶的,能夠和用戶定義的區分開來異步

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch 是一個實例方法
vm.$watch('a', function (newValue, oldValue) {
  // 這個回調將在 `vm.a` 改變後調用
})
複製代碼

created

  • el屬性對生命週期的影響

// 有el屬性的狀況下
new Vue({
el: '#app',
beforeCreate: function() {
  console.log('調用了beforeCreate')
},
created: function() {
  console.log('調用了created')
},
beforeMount: function() {
  console.log('調用了beforeMount')
},
mounted: function() {
  console.log('調用了mounted')
}
})

// 輸出結果
// 調用了beforeCreate
// 調用了created
// 調用了beforeMount
// 調用了mounted
複製代碼
// 在沒有el屬性的狀況下,沒有vm.$mount

new Vue({
beforeCreate: function() {
  console.log('調用了beforeCreate')
},
created: function() {
  console.log('調用了created')
},
beforeMount: function() {
  console.log('調用了beforeMount')
},
mounted: function() {
  console.log('調用了mounted')
}
})

// 輸出結果
// 調用了beforeCreate
// 調用了created
複製代碼
// 在沒有el屬性的狀況下,可是有vm.$mount方法

var vm = new Vue({
beforeCreate: function() {
  console.log('調用了beforeCreate')
},
created: function() {
  console.log('調用了created')
},
beforeMount: function() {
  console.log('調用了beforeMount')
},
mounted: function() {
  console.log('調用了mounted')
}
})

vm.$mount('#app')

// 輸出結果
// 調用了beforeCreate
// 調用了created
// 調用了beforeMount
// 調用了mounted
複製代碼
  • template屬性對生命週期的影響

這裏面分三種狀況:ide

一、在實例內部有template屬性的時候,直接用內部的,而後調用render函數去渲染。 二、在實例內部沒有找到template,就調用外部的html。實例內部的template屬性比外部的優先級高。 三、要是前二者都不知足,那麼就拋出錯誤。函數

咱們來看如下幾個例子:ui

new Vue({
  el: '#app',
  template: '<div id="app">hello world</div>'
})

//頁面上渲染出了hello world
複製代碼
<div id="app">hello world</div>

new Vue({
  el: '#app'
})

// 頁面上渲染出了hello world
複製代碼
//二者都存在的時候

<div id="app">hello world2</div>

new Vue({
  el: '#app',
  template: '<div id="app">hello world1</div>'
})
// 頁面上渲染出了hello world1
複製代碼

從上述的例子能夠看出內部的優先外部的。

  • 關於這個生命週期中的一些問題:

一、爲何el屬性的判斷在template以前? 由於el是一個選擇器,好比上述例子中咱們用到的最多的是id選擇器app,vue實例須要用這個el去template中尋找對應的。

二、實際上,vue實例中還有一種render選項,咱們能夠從文檔上看一下他的用法:

new Vue({
  el: '#app',
  render() {
    return (...)
  }
})
複製代碼

三、上述三者的渲染優先級:render函數 > template屬性 > 外部html

四、vue編譯過程——把tempalte編譯成render函數的過程。

beforeMount和mounted

life-mounted.png

咱們先來看一個例子:

<div id="app">
  <p>{{message}}</p>
</div>

new Vue({
  el: '#app',
  data: {
    message: 1
  },
  beforeMount: function() {
    console.log('調用了beforeMount');
    console.log(this.message)
    console.log(this.$el)
  },
  mounted: function() {
    console.log('調用了mounted');
    console.log(this.message)
    console.log(this.$el)
  }
})

// 輸出的結果:
// 調用了beforeMount
// 1
// <div>
// </div>

// 調用了mounted
// 1
// <div id="app">
//  <p>1</p>
// </div>
複製代碼

建立vue實例的$el,而後用它替代el屬性。

beforeUpdate和updated

這個過程當中,咱們會發現,當一個數據發生改變時,你的視圖也將隨之改變,整個更新的過程是:數據改變——致使虛擬DOM的改變——調用這兩個生命鉤子去改變視圖

  • 重點:這個數據只有和模版中的數據綁定了纔會發生更新。
// 沒綁定的狀況

var vm = new Vue({
  el: '#app',
  template: '<div id="app"></div>',
  beforeUpdate: function() {
    console.log('調用了beforeUpdate')
  },
  updated: function() {
    console.log('調用了uodated')
  },
  data: {
    a: 1
  }
})

vm.a = 2
//這種狀況在控制檯中是什麼都不會輸出的。
複製代碼
var vm = new Vue({
  el: '#app',
  template: '<div id="app">{{a}}</div>',
  beforeUpdate: function() {
    console.log('調用了beforeUpdate')
  },
  updated: function() {
    console.log('調用了uodated')
  },
  data: {
    a: 1
  }
})

vm.a = 2

// 輸出結果:
// 調用了beforeUpdate
// 調用了uodated
複製代碼

beforeDestory和destoryed

在beferoDestory生命鉤子調用以前,全部實例均可以用,可是當調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。

幾個不經常使用的生命鉤子

  • activated:當組件激活的時候調用
  • deactivated:當組件停用的時候調用
  • errorCaptured:這個生命鉤子能夠看官網,2.5.0以後纔有的。當捕獲一個來自子孫組件的錯誤時被調用。

最後咱們用一個例子來過一遍生命週期

let vm = new Vue({
  el: '#app',
  data: {
    message: 1
  },
  template: '<div id="app"><p>{{message}}</p></div>',
  beforeCreate() {
    console.log('調用了beforeCreate')
    console.log(this.message)
    console.log(this.$el)
  },
  created() {
    console.log('調用了created')
    console.log(this.message)
    console.log(this.$el)
  },
  beforeMount() {
    console.log('調用了beforeMount')
    console.log(this.message)
    console.log(this.$el)
  },
  mounted() {
    console.log('調用了mounted')
    console.log(this.message)
    console.log(this.$el)
  },
  beforeUpdate() {
    console.log('調用了beforeUpdate')
    console.log(this.message)
    console.log(this.$el)
  },
  updated() {
    console.log('調用了updated')
    console.log(this.message)
    console.log(this.$el)
  },
  beforeDestory() {
    console.log('調用了beforeDestory')
    console.log(this.message)
    console.log(this.$el)
  },
  destoryed() {
    console.log('調用了Destoryed')
    console.log(this.message)
    console.log(this.$el)
  }
})

vm.message = 2
複製代碼
  • 輸出的結果:
// 調用了beforeCreate
// undefined
// undefined
// 調用了created
// 1
// undefined
// 調用了beforeMount
// 1
// <div></div>
// 調用了mounted
// 1
// <div id="app"><p>1</p></div>
// 調用了beforeUpdate
// 2
// <div id="app"><p>2</p></div>
// 調用了updated
// 2
// <div id="app"><p>2</p></div>
複製代碼
相關文章
相關標籤/搜索