生命週期能夠分爲四個階段,初始化階段,模板編譯階段,掛載階段,已掛載和卸載階段。html
render函數選項 > template參數 > 外部HTMLvue
new Vue({內部無el項}).$mount('#app')是延遲加載,同下面的語句相同ajax
new Vue({el:"#app",***})算法
<div id="app"> <p>{{ message }}</p> <h1>{{message + '這是在outer HTML中的'}}</h1> </div>
var app = new Vue({ el: '#app', data: { message : "xuxiao is boy" }, template:"<h1>{{message +'這是在template中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // } })
注意:這時候實例中的data選項尚未數據,因此在beforecreated中沒法訪問到data中的數據
注意:在beforecreated中千萬不要去修改data中賦值的數據,最先也要在create裏面去作(添加一些行爲)
在模板渲染成HTML前調用,即一般初始化一些屬性值,而後再渲染成視圖, 未掛載DOM;created時還沒完成掛載,沒法經過id等得到DOM元素;vue-router
若在此階段進行的 DOM 操做必定要放在 Vue.nextTick() 的回調函數中;由於created() 鉤子函數執行的時候 DOM 其實並未進行任何渲染c#
Vue.nextTick( [callback, context] ):在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。
在created後,beforemount前,會檢查el選項,沒有就會調用vm.$mount(),而後就會繼續檢查template,沒有的話就綁定el選項的html,進入beforemount後,編譯模板爲虛擬的DOM,,開始render,將虛擬DOM渲染到頁面上;後端
從created到beforeMount的過程當中,數組
var app = new Vue({ el: '#app', data: { message : "xuxiao is boy" }, template:"<h1>{{message +'這是在template中的'}}</h1>", // render: function(createElement) { // return createElement('h1', 'this is createElement') // },
首先會判斷vue實例中有沒有el選項,若是有的話則進行下面的編譯,可是若是沒有el選項,則中止生命週期,直到vue實例上調用vm.$mount(el)。緩存
若是有el,再判斷是否有template參數,若是有,則把其看成模板編譯成render函數,
app
若是沒有,則把外部的html做爲模板編譯。template中的模板優先級高於outer HTML模板。
這是把outerHTML看成模板編譯了
<div id="app">
<p>{{ message }}</p> <h1>{{message + '這是在outer HTML中的'}}</h1>
</div>
若是把實例中render function選項的註釋去掉,則直接用render function裏的,獲得網頁以下
因此按優先級來講 render function>template>outerHTML
————————————————
在vue對象中還有一個render函數,它是以createElement做爲參數,而後作渲染操做,並且咱們能夠直接嵌入JSX.
綜合排名優先級:render函數選項 > template選項 > outer HTML.
在這個階段,$el還只是咱們在HTML裏面寫的節點。$el屬性已存在,是虛擬dom,只是數據未掛載到模板中;有了el,編譯了template|/outerHTML 能找到對應的template,並編譯成render函數
完成建立vm,
完成el的雙向綁定,完成掛載dom和渲染,能夠在這個階段對掛載的DOM進行操做;
ref 可在這發起後端請求,拿回數據,配合路由鉤子作一些事情; 可對DOM 進行操做
載入後html已經渲染(ajax請求能夠放在這個函數中),把vue實例中的data裏的message掛載到BOM節點中去
更新前狀態(view層的數據變化前,不是data中的數據改變前),從新渲染以前觸發,而後vue的虛擬dom機制會從新構建虛擬dom與上一次的虛擬dom樹利用diff算法進行對比以後從新渲染
數據已經更改完成,dom也從新render完成【具體的能夠用this.$el.innerHTML能夠看出已經改變了】
完成虛擬DOM的從新渲染和打補丁; 組件DOM 已完成更新; 可執行依賴的dom 操做 注意:不要在此函數中操做數據,會陷入死循環的。
當這個鉤子被調用時,組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。然而在大多數狀況下,你應該避免在此期間更改狀態。若是要相應狀態改變,一般最好使用計算屬性或 watcher取而代之。
view層的數據更新後,data中的數據同beforeUpdate,都是更新完之後的。注意:會發現
beforeUpdate
和updated
鉤子函數中的$el
同樣,根據官方理解beforeUpdate
應該指向虛擬dom,因此纔會同樣,而dom中的真正內容不同,可是beforeMount
和mouted
鉤子函數中爲何又會有區別呢?感受是設計的不足之處。**_
keep-alive 組件被移除時使用
實例銷燬以前調用。在這一步,實例仍然徹底可用。
說明:
beforeDestroy(){ console.group('beforeDestroy 銷燬前狀態==========>>'); console.log("%c%s", "color:red", "el : "+this.$el); //[object HTMLDivElement] console.log(this.$el); console.log("%c%s", "color:red", "data : "+this.$data); //[object Object] console.log("%c%s", "color:red", "message: "+this.message); //今天週二了!!! },
官方解釋:Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。
說明:執行destroy方法後,對data的改變不會再觸發周期函數,此時的vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在。
destroyed(){ console.group('destroyed 銷燬完成狀態==========>>'); console.log("%c%s", "color:red", "el : "+this.$el); //[object HTMLDivElement] console.log(this.$el); console.log("%c%s", "color:red", "data : "+this.$data); //[object Object] console.log("%c%s", "color:red", "message: "+this.message); //今天週二了!!! },
加載渲染過程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子組件更新過程
父beforeUpdate->子beforeUpdate->子updated->父updated
父組件更新過程
父beforeUpdate->父updated
銷燬過程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
參考文章:
http://www.javashuo.com/article/p-qhbnffir-gw.html
http://www.javashuo.com/article/p-vbplkdch-hs.html
https://www.jianshu.com/p/7026b73bb626