為什么要自造beforeEnter鉤子函數(shù)?
看下問(wèn)題場(chǎng)景:項(xiàng)目中有一單詞列表頁(yè)面,每個(gè)cell都會(huì)備注該單詞是否已經(jīng)掌握,點(diǎn)擊cell進(jìn)入詳情頁(yè),可對(duì)該單詞進(jìn)行學(xué)習(xí),并標(biāo)記單詞是否掌握,并且在詳情頁(yè)面中也可以通過(guò)點(diǎn)擊前進(jìn) 后退 按鈕學(xué)習(xí)其他的單詞。所以但我點(diǎn)擊返回時(shí),單詞列表要展示所有單詞用戶掌握的最新情況。
最終的頁(yè)面關(guān)系是這樣的:
wordListPage ——> wordDetail (對(duì)一系列單詞進(jìn)行學(xué)習(xí),退出)——> wordListPage(刷新單詞列表)
對(duì)于上面的場(chǎng)景,使用Vue生命周期函數(shù)是不行的,因?yàn)閂ue的生命周期函數(shù)如:beforeCreate 、created、beforeMounted、mounted等,只有在組件初始化的時(shí)候才會(huì)被調(diào)用,但是當(dāng)組件(VM實(shí)例)來(lái)自于緩存(如$route.go(-1) 、keep-alive)中時(shí),生命周期函數(shù)將不會(huì)再被調(diào)用。因此,當(dāng)我從單詞詳情頁(yè)面返回至列表頁(yè)面時(shí),找不到一個(gè)恰當(dāng)?shù)臅r(shí)期去出發(fā)數(shù)據(jù)更新。所以上面的場(chǎng)景也就無(wú)法很好的去做處理。
當(dāng)然,對(duì)于上面的場(chǎng)景是比較少的,但是beforeEnter鉤子函數(shù)的存在還是有必要的。
構(gòu)造beforeEnter鉤子函數(shù)
依賴知識(shí)點(diǎn):
1.創(chuàng)建一個(gè)中央事件總線
對(duì)于中央事件總線,簡(jiǎn)單理解,就是創(chuàng)建一個(gè)公共Vue實(shí)例(EventBus),在不同的地方使用相同實(shí)例觸發(fā)EventBus.$emit('demo') 消息,在想要監(jiān)聽事件的位置使用公共Vue實(shí)例進(jìn)行監(jiān)聽EventBus.$on('demo',() => {})。再說(shuō)白點(diǎn),就是有這么一個(gè)公共組件,它會(huì)再不同的地方發(fā)消息,又在不同的地方自己去監(jiān)聽消息。所以說(shuō)消息的發(fā)送和接收都是它自己實(shí)現(xiàn)的,所以說(shuō)我們稱之為中央事件總線。
代碼如下:libs/EventBus.js
import Vue from 'vue'; const EventBus = new Vue(); export default EventBus;
下面看下怎么使用
2.路由鉤子函數(shù)beforeEach
通過(guò)beforeEach鉤子函數(shù),實(shí)現(xiàn)路由切換時(shí)觸發(fā)相應(yīng)組件的beforeEnter事件。
代碼如下:router/index.js
import EventBus from '@/libs/EventBus'; router.beforeEach((to, from, next) => { //如:EventBus.$emit('homeBeforeEnter'); EventBus.$emit(to.name + 'BeforeEnter'); if (to.matched.some(route => route.meta.isAuth)) { ... next() } else { next() } })
3.創(chuàng)建全局混入對(duì)象
這里實(shí)現(xiàn)路由切換事件的監(jiān)聽和組件實(shí)例鉤子函數(shù)beforeEnter的觸發(fā)。
libs/beforeEnterMixin.js
import EventBus from './EventBus'; export default { beforeCreate() { //獲取當(dāng)前路由名稱,與前面使用to.name對(duì)應(yīng) let vmName = this.$route.name; if (!vmName) { return; } // 當(dāng)組件初始化時(shí),先觸發(fā)一次,后續(xù)將不再調(diào)用 this.$options.beforeEnter(); const beforeEnter = vmName + 'BeforeEnter'; //監(jiān)聽路由切換時(shí)觸發(fā)的...BeforeEnter事件 //通過(guò)this.$options獲取到實(shí)例中的beforeEnter鉤子函數(shù) //監(jiān)聽到...BeforeEnter事件后,觸發(fā)鉤子函數(shù)beforeEnter調(diào)用 EventBus.$on(beforeEnter, this.$options.beforeEnter); }, //該函數(shù)在這里只作為占位,沒(méi)有實(shí)際意義 beforeEnter() {} };
對(duì)于該混入對(duì)象,使用全局或者局部混入都是可行的。
全局混入:main.js
import beforeEnterMixin from '@/libs/beforeEnterMixin'; Vue.mixin(beforeEnterMixin);
4.在組件中的使用
如:home.vue
<template> <div> 首頁(yè) </div> </template> <script> export default { beforeEnter() { console.log('首頁(yè) beforeEnter...'); }, created() { console.log('首頁(yè) created...') } } </script>
至此,我們的 beforeEnter 就完成了,可以做個(gè)demo自己測(cè)試下,目前本人在項(xiàng)目比較多的地方都會(huì)用到它。
在此附上以上代碼的demo鏈接:https://github.com/chaoshenr/Vue-beforeEnter
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com