【Vue】詳解Vue生命周期


 

 

 

Vue實例的生命周期全過程(圖)

 

(這里的紅邊圓角矩形內的都是對應的Vue實例的鈎子函數)

在beforeCreate和created鈎子函數間的生命周期

 

在beforeCreate和created之間,進行數據觀測(data observer) ,也就是在這個時候開始監控data中的數據變化了,同時初始化事件
 
 

created鈎子函數和beforeMount間的生命周期

 

對於created鈎子函數和beforeMount間可能會讓人感到有些迷惑,下面我就來解釋一下:

el選項的有無對生命周期過程的影響

首先系統會判斷對象中有沒有el選項
有el選項,則繼續編譯過程
沒有el選項,則停止編譯,也意味着暫時停止了生命周期,直到vm.$mount(el)
下面我展示一下:
new Vue({
  el: '#app',
  beforeCreate: function () {
    console.log('調用了beforeCreat鈎子函數')
  },
  created: function () {
    console.log('調用了created鈎子函數')
  },
  beforeMount: function () {
    console.log('調用了beforeMount鈎子函數')
  },
  mounted: function () {
    console.log('調用了mounted鈎子函數')
  }
})

 

demo如下:

 

可以看到,在el選項填寫且正確的時候,生命周期將正常進行
 
而當我們把el去掉:
new Vue({
  beforeCreate: function () {
    console.log('調用了beforeCreat鈎子函數')
  },
  created: function () {
    console.log('調用了created鈎子函數')
  },
  beforeMount: function () {
    console.log('調用了beforeMount鈎子函數')
  },
  mounted: function () {
    console.log('調用了mounted鈎子函數')
  }
})

 

demo:
 

 

可以看到,生命周期的鈎子函數執行到created就結束了
而當我們不加el選項,但是手動執行vm.$mount(el)方法的話,也能夠使暫停的生命周期進行下去,例如:
var vm = new Vue({
  beforeCreate: function () {
    console.log('調用了beforeCreat鈎子函數')
  },
  created: function () {
    console.log('調用了created鈎子函數')
  },
  beforeMount: function () {
    console.log('調用了beforeMount鈎子函數')
  },
  mounted: function () {
    console.log('調用了mounted鈎子函數')
  }
})
vm.$mount('#app')

 

demo如下,可以看到,這個時候雖然對象中沒有el參數,但通過$mount(el)動態添加的方式,也能夠使生命周期順利進行
 

 

template參數選項的有無對生命周期的影響

 

 

1.如果Vue實例對象中有template參數選項,則將其作為模板編譯成render函數
2.如果沒有template參數選項,則將外部的HTML作為模板編譯(template),也就是說,template參數選項的優先級要比外部的HTML高
3.如果1,2條件都不具備,則報錯
 
我們可以把模板寫在template參數選項中:
new Vue({
  el: '#app',
  template: '<div id="app"><p>模板在templated參數中找到了喲~</p></div>'
})
demo:

 

 

 

也可以把參數選項寫在外部HTML中,像這樣:
 
外部HTML:
<div id="app"><p>模板是在外部HTML中找到的~</p></div>
創建對象實例:
new Vue({
  el: '#app'
})

 

demo:

 

那么有趣的問題來了,當模板同時放在template參數選項和外部HTML中,會怎樣呢?
例如:
外部HTML:
<div id="app"><p>模板是在外部HTML中找到的~</p></div>

 

 
創建Vue實例(包含template參數選項)
new Vue({
  el: '#app',
  template: '<div id="app"><p>模板在templated參數中找到了喲~</p></div>'
})

 

demo如下:

 

很顯然,正如我上面下的結論一樣,最終顯示的是“模板在templated參數中找到了喲~”而不是“模板是在外部HTML中找到的~”,因為template參數的優先級比外部HTML的優先級要高
 
【注意】
1.為什么判斷el要發生在判斷template前面呢
 
因為Vue需要通過el的“選擇器”找到對應的template。總結一下上述的過程,Vue通過el參數去找到對應的template。然后,根據el參數給出的“選擇器”,首先去Vue實例對象本身的template選項參數中找,如果沒有template參數,則到外部HTML中尋找,找到后將模板編譯成render函數
 
2.實際上,在Vue中,有render函數這個選項,它以createElement作為參數,做渲染操作。當然你也可以不調用createElement,而直接嵌入JSX(學習react的同學對此應該很熟悉吧)。
new Vue({
  el: '#demo',
  render (createElement) {
    return (....)
  }
})

 

【注意】render選項參數比template更接近Vue解析器!所以綜合排列如下:
render函數選項  > template參數  > 外部HTML
 

Vue的編譯過程——把模板編譯成 render 函數

Vue的編譯實際上是指Vue把模板編譯成 render 函數的過程
 
我們可以通過Vue.compile這個實時編譯模板的函數來看一看:
用官方文檔的例子做個解釋:
<div>
  <header>
    <h1>I'm a template!</h1>
  </header>
  <p v-if="message">
    {{ message }}
  </p>
  <p v-else>
    No message.
  </p>
</div>

 

  
會被渲染成
function anonymous() {
  with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])}
}

 

beforeMount和mounted鈎子函數間的生命周期

 

 

對於這一點,我也感到有些迷惑,百度后之后也沒什么頭緒,最后我思考的結果是這樣的:正因為render函數和template選項的“優先級”比外部HTML要高,所以,最后一般會存在一個外部HTML模板被Vue實例本身配置的模板所“替代”的過程也就是上圖所說的 “replace”
 
(如果大家有不同意見也可以在評論處一起討論)
 

beforeUpdate鈎子函數和updated鈎子函數間的生命周期

 

 

在Vue中,數據更改會導致虛擬 DOM 重新渲染,並先后調用beforeUpdate鈎子函數和updated鈎子函數
 
但要注意一點:重渲染(調用這兩個鈎子函數)的前提是被更改的數據已經被寫入模板中!!(這點很重要)
例如:
var vm = new Vue({
  el: '#app',
  data: {
    number: 1
  },
  template: '<div id="app"><p></p></div>',
  beforeUpdate: function () {
    console.log('調用了beforeUpdate鈎子函數')
  },
  updated: function () {
    console.log('調用了updated鈎子函數')
  }
})
 
vm.number = 2

 

 

 

控制台上並沒有如我們預料那樣輸出調用兩個鈎子函數的文本
而當我們改成
var vm = new Vue({
  el: '#app',
  data: {
    number: 1
  },
  // 在模板中使用number這個數據
  template: '<div id="app"><p>  {{ number }} </p></div>',
  beforeUpdate: function () {
    console.log('調用了beforeUpdate鈎子函數')
  },
  updated: function () {
    console.log('調用了updated鈎子函數')
  }
})
 
vm.number = 2
 

 

 

 
這個時候,調用兩個鈎子函數的文本就被輸出來了
總之,只有Vue實例中的數據被“寫入”到我們的模板中,它的改變才可以被Vue追蹤,重渲染從而調用 beforeUpdate鈎子函數和updated鈎子函數
 

beforeDestroy和destroyed鈎子函數間的生命周期

 

 

beforeDestroy鈎子函數在實例銷毀之前調用。在這一步,實例仍然完全可用。
 
destroyed鈎子函數在Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
 
【注意】就如同調用在Vue實例上調用$mounted會使暫停的生命周期繼續一樣,調用$destroy()會直接銷毀實例
 
 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM