場景:vue-router
路由鉤子 beforeRouteEnter
可以用來在初始進入頁面前,http 異步獲取數據mockData
,預先判斷是進入 A 頁、還是 B 頁,還是留在本頁;而如果留在本頁的話,還需要在mounted
根據mockData
來判斷顯示哪種狀態(可以在本頁面實例創建後,重新發起 http 請求獲取mockData
,但是沒有必要,造成代碼冗餘);
執行順序:
async beforeRouteEnter(to, from, next) {
let res = await gameData()
console.log('beforeRouteEnter start');
next(vm => {
console.log("vm start")
vm.is_exchange = res.is_exchange
vm.is_finish = res.is_finish
})
},
beforeCreate() {
console.log("beforeCreate start")
},
mounted(){
console.log('mounted start');
if(this.is_finish){
this.modalMsg="活動已結束"
return;
}
if(this.is_exchange){
this.modalMsg="您已兌換獎品"
return;
}
}
打印結果如下:
beforeRouteEnter start
beforeCreate start
mounted start
vm start
由打印結果,我們可以總結 beforeRouteEnter
鉤子確實在 vue 實例創建前執行,但是其 next
函數中 vm
回調不是同步執行,而是等到 mounted
執行完之後,才執行。
癥結: 因爲我們要根據mockData
中的is_exchange
和is_finish
參數來判斷決定頁面初始狀態,此過程需要在mounted
中執行;但是 mounted
執行時,vm
還未執行,即 mounted
拿不到is_exchange
和is_finish
這兩個值,這樣就造成了衝突;
解決: 在 next
中 打印 vm
,發現 vm
就是當前 vue 實例對象,即可以使用 vm
調用所有當前實例的變量和方法;那依次,能否將判斷邏輯寫入 methods
中一個方法中,使用 vm
來調用呢?
async beforeRouteEnter(to, from, next) {
let res = await gameData()
console.log('beforeRouteEnter start');
next(vm => {
console.log("vm start")
vm.is_exchange = res.is_exchange
vm.is_finish = res.is_finish
vm.judge();//賦值之後,此處調用判斷方法
})
},
beforeCreate() {
console.log("beforeCreate start")
},
mounted(){
console.log('mounted start');
},
methods:{
judge(){// 將判斷邏輯寫入judge方法
if(this.is_finish){
this.modalMsg="活動已結束"
return;
}
if(this.is_exchange){
this.modalMsg="您已兌換獎品"
return;
}
}
}
至此,問題解決。有同學可能會問,在 vm
中調用 judge
方法時,mounted
已執行,此時頁面已渲染,再去判斷初始狀態,會不會有閃爍問題?本人經過測試,發現不會,據此推斷,在 mounted
執行結束之後,頁面沒有開始更新動作,而是在執行完 vm
回調之後,再去渲染。這樣的話,邏輯上就行得通了,但是這個只是推斷,還需要在源碼層面找到依據纔可以。