實例生命周期:
https://segmentfault.com/a/1190000008570622.jpg
image.png
-
beforeCreate
:在實例初始化之后脚囊,數(shù)據(jù)觀測data observer(props、data芦拿、computed
) 和event/watcher
事件配置之前被調用士飒。 -
created
:實例已經創(chuàng)建完成之后被調用。在這一步蔗崎,實例已完成以下的配置:數(shù)據(jù)觀測(data observer)酵幕,屬性和方法的運算,watch/event
事件回調缓苛。然而芳撒,掛載階段還沒開始,$el
屬性目前不可見未桥。 -
beforeMount
:在掛載開始之前被調用:相關的render
函數(shù)首次被調用番官。 -
mounted
:el
被新創(chuàng)建的vm.$el
替換,并掛載到實例上去之后調用該鉤子钢属。 -
beforeUpdate
:數(shù)據(jù)更新時調用,發(fā)生在虛擬DOM
重新渲染和打補丁之前门躯。 你可以在這個鉤子中進一步地更改狀態(tài)淆党,這不會觸發(fā)附加的重渲染過程。 -
updated
:無論是組件本身的數(shù)據(jù)變更,還是從父組件接收到的props
或者從vuex
里面拿到的數(shù)據(jù)有變更染乌,都會觸發(fā)虛擬DOM
重新渲染和打補丁山孔,并在之后調用updated
。 -
beforeDestroy
:實例銷毀之前調用荷憋。在這一步台颠,實例仍然完全可用。 -
destroyed
:Vue
實例銷毀后調用勒庄。調用后串前,Vue
實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除实蔽,所有的子實例也會被銷毀荡碾。 該鉤子在服務器端渲染期間不被調用。
注意:
created
階段的ajax
請求與mounted
請求的區(qū)別:前者頁面視圖未出現(xiàn)局装,如果請求信息過多坛吁,頁面會長時間處于白屏狀態(tài)。
單個組件的生命周期
- 初始化組件時铐尚,僅執(zhí)行了
beforeCreate/Created/beforeMount/mounted
四個鉤子函數(shù) - 當改變data中定義的變量(響應式變量)時拨脉,會執(zhí)行
beforeUpdate/updated
鉤子函數(shù) - 當切換組件(當前組件未緩存)時,會執(zhí)行
beforeDestory/destroyed
鉤子函數(shù) - 初始化和銷毀時的生命鉤子函數(shù)均只會執(zhí)行一次宣增,
beforeUpdate/updated
可多次執(zhí)行
Vue.nextTick():
在下次
DOM
更新循環(huán)結束之后執(zhí)行延遲回調玫膀。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的DOM
统舀。
獲取更新后的DOM
言外之意就是什么操作需要用到了更新后的DOM
而不能使用之前的DOM
或者使用更新前的DOM
會出問題匆骗,所以就衍生出了這個獲取更新后的 DOM
的Vue
方法。所以放在Vue.nextTick()
回調函數(shù)中的執(zhí)行的應該是會對DOM
進行操作的 js
代碼誉简,比如Swiper擴展包的:
var swiper = new Swiper('.swiper-container', {
pagination: '.swiper-pagination',
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
paginationClickable: true,
spaceBetween: 30,
centeredSlides: true,
autoplay: 2500,
autoplayDisableOnInteraction: false
});
什么時候需要用Vue.nextTick()
:
- 你在
Vue
生命周期的created()鉤子函數(shù)進行的DOM
操作一定要放在Vue.nextTick()
的回調函數(shù)中碉就。原因是什么呢,原因是在created()
鉤子函數(shù)執(zhí)行的時候DOM
其實并未進行任何渲染闷串,而此時進行DOM
操作無異于徒勞瓮钥,所以此處一定要將DOM
操作的js
代碼放進Vue.nextTick()
的回調函數(shù)中。與之對應的就是mounted鉤子函數(shù)烹吵,因為該鉤子函數(shù)執(zhí)行時所有的DOM
掛載和渲染都已完成碉熄,此時在該鉤子函數(shù)中進行任何DOM
操作都不會有問題 。 - 在數(shù)據(jù)變化后要執(zhí)行的某個操作肋拔,當你設置
vm.someData = 'new value'
锈津,DOM
并不會馬上更新,而是在異步隊列被清除凉蜂,也就是下一個事件循環(huán)開始時執(zhí)行更新時才會進行必要的DOM
更新琼梆。如果此時你想要根據(jù)更新的DOM
狀態(tài)去做某些事情性誉,就會出現(xiàn)問題。茎杂。為了在數(shù)據(jù)變化之后等待Vue
完成更新DOM
错览,可以在數(shù)據(jù)變化之后立即使用Vue.nextTick(callback)
。這樣回調函數(shù)在DOM
更新完成后就會調用煌往。 -
mounted
不會承諾所有的子組件也都一起被掛載倾哺。如果你希望等到整個視圖都渲染完畢,可以用vm.$nextTick
替換掉mounted
:
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
2021.9.7補充:為什么nextTick里的代碼會在DOM更新后執(zhí)行
先看一段代碼:
this.$nextTick(() => {
console.log('獲取最新dom1:', this.$refs.con) // 1
// debugger
})
this.value++ // 2 這里實際上會執(zhí)行 watcher.run()
this.$nextTick(() => {
console.log('獲取最新dom2:', this.$refs.con) // 3
// debugger
})
打印結果如下:
但是如果把
this.value++
和第一個nextTick調換位置刽脖,兩個nextTick都能獲取到最新的dom了羞海。是什么原因,我們來從vue的源碼分析一下:this.value++
-> 觸發(fā)set函數(shù)
-> 通知依賴更新: dep.notify()
-> 調用 watcher.update()
-> watcher.run()放在vue的nextTick函數(shù)中執(zhí)行
-> flushCallbacks調用隊列中的所有cb曾棕,執(zhí)行順序為1扣猫、2、3
-> 執(zhí)行到2的時候調用_render 翘地、_update申尤、patch更新dom
所以執(zhí)行到1的時候dom是沒有進行更新的,因此打印的也是沒有更新的dom衙耕,執(zhí)行到2的時候已經完成了patch昧穿,dom更新了,因此拿到的是新的dom橙喘。
這個流程走完后时鸵,vue替換掉了老的dom節(jié)點,這時候dom樹已經是新的了厅瞎,所以在JS中獲取dom數(shù)據(jù)也是新的饰潜,但是視圖不一定更新了,因為不一定完成了繪制(這個正確性還有待考證)和簸。
參考文章:
https://mp.weixin.qq.com/s/4ukhHAcMQN07y0ssYqUeuA
https://segmentfault.com/a/1190000008570622
https://segmentfault.com/a/1190000008570874