先上圖
遇到的一個(gè)問題
在我的項(xiàng)目中击儡,常用的生命周期鉤子函數(shù)一直都是mounted袄秩,對(duì)于大部分情況现柠,都是屢試不爽苹享、捷報(bào)頻傳~
但是在前幾天卻遭遇了一個(gè)意外双絮,我在mounted中獲取后臺(tái)數(shù)據(jù)并更新data,在template中把data.fullname與一個(gè)p元素的innerHTML綁定得问,這是一個(gè)簡(jiǎn)單到不能再簡(jiǎn)單掷邦,普通到不能更普通的操作,打開瀏覽器一看椭赋,完美抚岗!fullname的數(shù)據(jù)正常顯示在p元素中,沒有任何問題哪怔,可是……咦宣蔚,控制臺(tái)怎么報(bào)錯(cuò)了?
報(bào)錯(cuò)信息的大致意思是认境,data是null胚委,無(wú)法獲取到null的fullname屬性,可是數(shù)據(jù)明明正常顯示了呀叉信,而且我們不是從后臺(tái)請(qǐng)求數(shù)據(jù)并給data賦值了嘛亩冬?
經(jīng)過一番排查,發(fā)現(xiàn)原因有兩處:
- 初始化時(shí)硼身,給data的值是null
data () {
return {
data: null,
},
- vue渲染template的時(shí)間在beforeMount之后硅急,mounted之前,所以渲染template時(shí)data值為null佳遂,故而報(bào)錯(cuò)营袜;但是待后臺(tái)數(shù)據(jù)請(qǐng)求成功給data賦值后,p元素能監(jiān)聽到數(shù)據(jù)的變化丑罪,然后更新其innerHTML荚板,所以UI看起來(lái)是很正常的
解決方案
所以解決方案是非常簡(jiǎn)單的凤壁,只需要保證渲染template的時(shí)候,data已經(jīng)拿到后臺(tái)數(shù)據(jù)就可以了跪另,所以可以把mounted鉤子函數(shù)修改為beforeMount拧抖,或者其他更早被調(diào)用的鉤子函數(shù):beforeCreated、created等
后來(lái)經(jīng)過驗(yàn)證免绿,上述的解決方案是錯(cuò)誤的唧席,因?yàn)樗会槍?duì)同步代碼有效果。而ajax請(qǐng)求是異步操作针姿,回調(diào)函數(shù)的執(zhí)行時(shí)間不能確定袱吆,所以即使放在created鉤子函數(shù)中厌衙,也不能保證在mounted之前完成數(shù)據(jù)的請(qǐng)求……
所以最終的解決方案是距淫,給p標(biāo)簽加一個(gè)v-if,待data不為null時(shí)再進(jìn)行渲染婶希,但并不算很優(yōu)雅榕暇。
不知道vue的生命周期鉤子函數(shù)是否支持promise或者async/await,如果大神們有更好的解決方案喻杈,歡迎交流~
總結(jié)
一點(diǎn)小小的感悟彤枢,vue生命周期鉤子函數(shù)的使用并非一成不變的,要根據(jù)不同的應(yīng)用場(chǎng)景而有所改變筒饰,稍微總結(jié)一下:
beforeCreate:在實(shí)例初始化之后缴啡,**數(shù)據(jù)觀測(cè)(data observer) ** 和 event/watcher事件配置 之前被調(diào)用,注意是 之前瓷们,此時(shí)data业栅、watcher、methods統(tǒng)統(tǒng)滴沒有谬晕。
這個(gè)時(shí)候的vue實(shí)例還什么都沒有碘裕,但是$route對(duì)象是存在的,可以根據(jù)路由信息進(jìn)行重定向之類的操作攒钳。created:在實(shí)例已經(jīng)創(chuàng)建完成之后被調(diào)用帮孔。在這一步,實(shí)例已完成以下配置:數(shù)據(jù)觀測(cè)(data observer) 不撑,屬性和方法的運(yùn)算文兢, watch/event 事件回調(diào)。然而焕檬,掛載階段還沒開始禽作,$el屬性目前不可見。
此時(shí) this.$data 可以訪問揩页,watcher旷偿、events烹俗、methods也出現(xiàn)了,若根據(jù)后臺(tái)接口動(dòng)態(tài)改變data和methods的場(chǎng)景下萍程,可以使用幢妄。beforeMount:在掛載開始之前被調(diào)用,相關(guān)的 render 函數(shù) 首次被調(diào)用茫负。但是render正在執(zhí)行中蕉鸳,此時(shí)DOM還是無(wú)法操作的。我打印了此時(shí)的vue實(shí)例對(duì)象忍法,相比于created生命周期潮尝,此時(shí)只是多了一個(gè)$el的屬性,然而其值為undefined饿序。
使用場(chǎng)景我上文已經(jīng)提到了勉失,頁(yè)面渲染時(shí)所需要的數(shù)據(jù),應(yīng)盡量在這之前完成賦值原探。mounted:在掛載之后被調(diào)用乱凿。在這一步 創(chuàng)建vm.$el并替換el,并掛載到實(shí)例上咽弦。(官方文檔中的 “如果root實(shí)例掛載了一個(gè)文檔內(nèi)元素徒蟆,當(dāng)mounted被調(diào)用時(shí)vm.$el也在文檔內(nèi)” 這句話存疑)
此時(shí)元素已經(jīng)渲染完成了,依賴于DOM的代碼就放在這里吧~比如監(jiān)聽DOM事件型型。beforeUpdate:$vm.data更新之后段审,虛擬DOM重新渲染 和打補(bǔ)丁之前被調(diào)用。
你可以在這個(gè)鉤子中進(jìn)一步地修改$vm.data闹蒜,這不會(huì)觸發(fā)附加的重渲染過程寺枉。updated:虛擬DOM重新渲染 和打補(bǔ)丁之后被調(diào)用。
當(dāng)這個(gè)鉤子被調(diào)用時(shí)嫂用,組件DOM的data已經(jīng)更新型凳,所以你現(xiàn)在可以執(zhí)行依賴于DOM的操作。但是不要在此時(shí)修改data嘱函,否則會(huì)繼續(xù)觸發(fā)beforeUpdate甘畅、updated這兩個(gè)生命周期,進(jìn)入死循環(huán)往弓!beforeDestroy:實(shí)例被銷毀之前調(diào)用疏唾。在這一步,實(shí)例仍然完全可用函似。
實(shí)例要被銷毀了槐脏,趕在被銷毀之前搞點(diǎn)事情吧哈哈~destroyed:Vue實(shí)例銷毀后調(diào)用。此時(shí)撇寞,Vue實(shí)例指示的所有東西已經(jīng)解綁定顿天,所有的事件監(jiān)聽器都已經(jīng)被移除堂氯,所有的子實(shí)例也已經(jīng)被銷毀。
這時(shí)候能做的事情已經(jīng)不多了牌废,只能加點(diǎn)兒提示toast之類的東西吧咽白。
注:beforeMount、mounted鸟缕、beforeUpdate晶框、updated、beforeDestroy懂从、destroyed這幾個(gè)鉤子函數(shù)授段,在服務(wù)器端渲染期間不被調(diào)用。