99久久精品国产片-99久久精品国产免费-99久久精品国产麻豆-99久久精品国产国产毛片-99久久精品国产高清一区二区-99久久精品费精品国产一区二区

vue-router 導航守衛中 next 控制實現

2020-5-14    seo達人

使用 vue-router 的導航守衛鉤子函數,某些鉤子函數可以讓開發者根據業務邏輯,控制是否進行下一步,或者進入到指定的路由。


例如,后臺管理頁面,會在進入路由前,進行必要登錄、權限判斷,來決定去往哪個路由,以下是偽代碼:


// 全局導航守衛

router.beforEach((to, from, next) => {

 if('no login'){

   next('/login')

 }else if('admin') {

   next('/admin')

 }else {

   next()

 }

})


// 路由配置鉤子函數

{

 path: '',

 component: component,

 beforeEnter: (to, from, next) => {

   next()

 }

}


// 組件中配置鉤子函數

{

 template: '',

 beforeRouteEnter(to, from, next) {

   next()

 }

}

調用 next,意味著繼續進行下面的流程;不調用,則直接終止,導致路由中設置的組件無法渲染,會出現頁面一片空白的現象。


鉤子函數有不同的作用,例如 beforEach,afterEach,beforeEnter,beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave,針對這些注冊的鉤子函數,要依次進行執行,并且在必要環節有控制權決定是否繼續進入到下一個鉤子函數中。


以下分析下源碼中實現的方式,而源碼中處理的邊界情況比較多,需要抓住核心點,去掉冗余代碼,精簡出便于理解的實現。


精簡源碼核心功能

總結下核心點:鉤子函數注冊的回調函數,能順序執行,同時會將控制權交給開發者。


先來一個能夠注冊回調函數的類:


class VueRouter {

 constructor(){

   this.beforeHooks = []

   this.beforeEnterHooks = []


   this.afterHooks = []

 }


 beforEach(callback){

   return registerHook(this.beforeHooks, callback)

 }

 beforeEnter(callback){

   return registerHook(this.beforeEnterHooks, callback)

 }

 afterEach(callback){

   return registerHook(this.afterHooks, callback)

 }

}

function registerHook (list, fn) {

 list.push(fn)

 return () => {

   const i = list.indexOf(fn)

   if (i > -1) list.splice(i, 1)

 }

}

聲明的類,提供了 beforEach 、beforeEnter 和 afterEach 來注冊必要的回調函數。


抽象出一個 registerHook 公共方法,作用:


注冊回調函數

返回的函數,可以取消注冊的回調函數

使用一下:


const router = new VueRouter()


const beforEach = router.beforEach((to, from, next) => {

 console.log('beforEach');

 next()

})

// 取消注冊的函數

beforEach()

以上的回調函數會被取消,意味著不會執行了。



router.beforEach((to, from, next) => {

 console.log('beforEach');

 next()

})


router.beforeEnter((to, from, next) => {

 console.log('beforeEnter');

 next()

})


router.afterEach(() => {

 console.log('afterEach');

})

以上注冊的鉤子函數會依次執行。beforEach 和 beforeEnter 的回調接收內部傳來的參數,同時通過調用 next 可繼續走下面的回調函數,如果不調用,則直接被終止了。

最后一個 afterEach 在上面的回調函數都執行后,才被執行,且不接收任何參數。


先來實現依次執行,這是最簡單的方式,在類中增加 run 方法,手動調用:



class VueRouter {

 // ... 其他省略,增加 run 函數


 run(){

   // 把需要依次執行的回調存放在一個隊列中

   let queue = [].concat(

     this.beforeHooks,

     this.afterHooks

   )

   

   for(let i = 0; i < queue.length; i++){

     if(queue(i)) {

       queue(i)('to', 'from', () => {})

     }

   }

 }

}


// 手動調用


router.run()

打印:


'beforEach'

'beforeEnter'

上面把要依次執行的回調函數聚合在一個隊列中執行,并傳入必要的參數,但這樣開發者不能控制是否進行下一步,即便不執行 next 函數,依然會依次執行完隊列的函數。


改進一下:


class VueRouter {

 // ... 其他省略,增加 run 函數


 run(){

   // 把需要依次執行的回調存放在一個隊列中

   let queue = [].concat(

     this.beforeHooks,

     this.afterHooks

   )

   queue[0]('to', 'from', () => {

     queue[1]('to', 'from', () => {

      console.log('調用結束');

     })

   })

 }

}


router.beforEach((to, from, next) => {

 console.log('beforEach');

 // next()

})


router.beforeEnter((to, from, next) => {

 console.log('beforeEnter');

 next()

})

傳入的 next 函數會有調用下一個回調函數的行為,把控制權交給了開發者,調用了 next 函數會繼續執行下一個回調函數;不調用 next 函數,則終止了隊列的執行,所以打印結果是:


'beforEach'

上面實現有個弊端,代碼不夠靈活,手動一個個調用,在真實場景中無法確定注冊了多少個回調函數,所以需要繼續抽象成一個功能更強的方法:


function runQueue (queue, fn, cb) {

 const step = index => {

   // 隊列執行結束了

   if (index >= queue.length) {

     cb()

   } else {

     // 隊列有值

     if (queue[index]) {

       // 傳入隊列中回調,做一些必要的操作,第二個參數是為了進行下一個回調函數

       fn(queue[index], () => {

         step(index + 1)

       })

     } else {

       step(index + 1)

     }

   }

 }

 // 初次調用,從第一個開始

 step(0)

}

runQueue 就是執行隊列的通用方法。


第一個參數為回調函數隊列, 會依次取出來;

第二個參數是函數,它接受隊列中的函數,進行一些其他處理;并能進行下個回調函數的執行;

第三個參數是隊列執行結束后調用。

知道了這個函數的含義,來使用一下:



class VueRouter {

 // ... 其他省略,增加 run 函數


 run(){

   // 把需要依次執行的回調存放在一個隊列中

   let queue = [].concat(

     this.beforeHooks,

     this.beforeEnterHooks

   )


   // 接收回到函數,和進行下一個的執行函數

   const iterator = (hook, next) => {

     // 傳給回調函數的參數,第三個參數是函數,交給開發者調用,調用后進行下一個

     hook('to', 'from', () => {

       console.log('執行下一個回調時,處理一些相關信息');

       next()

     })

   }


   runQueue(queue, iterator, () => {


     console.log('執行結束');

     // 執行 afterEach 中的回調函數

     this.afterHooks.forEach((fn) => {

       fn()

     })

   })

 }

}

// 注冊

router.beforEach((to, from, next) => {

 console.log('beforEach');

 next()

})


router.beforeEnter((to, from, next) => {

 console.log('beforeEnter');

 next()

})


router.afterEach(() => {

 console.log('afterEach');

})


router.run();

從上面代碼可以看出來,每次把隊列 queue 中的回調函數傳給 iterator , 用 hook 接收,并調用。

傳給 hook 必要的參數,尤其是第三個參數,開發者在注冊的回調函數中調用,來控制進行下一步。

在隊列執行完畢后,依次執行 afterHooks 的回調函數,不傳入任何參數。


所以打印結果為:


beforEach

執行下一個回調時,處理一些相關信息

beforeEnter

執行下一個回調時,處理一些相關信息

執行結束

afterEach

以上實現的非常巧妙,再看 Vue-router 源碼這塊的實現方式,相信你會豁然開朗。

日歷

鏈接

個人資料

藍藍設計的小編 http://www.lapeinture.cn

存檔

美女免费精品视频在线观看| 日韩免费片| 人人干人人草| 99久久精品国产免费| 成人高清护士在线播放| 欧美激情一区二区三区视频 | 91麻豆精品国产自产在线 | 九九国产| 亚洲天堂在线播放| 人人干人人插| 可以免费看污视频的网站| 尤物视频网站在线| 九九精品在线播放| 高清一级片| 成人影视在线播放| 日韩专区第一页| 国产一区二区精品| 国产一区二区精品久| 国产视频一区在线| 国产一区二区精品在线观看| 99色视频在线| 欧美激情一区二区三区在线| 国产麻豆精品高清在线播放| 久久福利影视| 国产精品自拍亚洲| 日日夜夜婷婷| 韩国三级香港三级日本三级| 日韩中文字幕在线播放| 国产网站免费在线观看| 欧美激情影院| 久草免费资源| 国产麻豆精品免费视频| 欧美18性精品| 成人免费观看网欧美片| 亚洲女初尝黑人巨高清在线观看| 国产不卡精品一区二区三区| 欧美日本韩国| 日韩在线观看免费| 国产91素人搭讪系列天堂| 精品国产一区二区三区精东影业| 国产不卡在线观看视频| 国产网站免费在线观看| 天天做日日干| 亚洲精品影院| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 日韩女人做爰大片| 麻豆网站在线免费观看| 国产网站免费观看| 日韩中文字幕在线观看视频| 久久国产精品只做精品| 天天做人人爱夜夜爽2020| 国产一区精品| 国产网站免费视频| 国产不卡高清在线观看视频| 日日爽天天| a级黄色毛片免费播放视频| 国产极品精频在线观看| 国产高清视频免费| 91麻豆精品国产高清在线| 国产成人精品在线| 高清一级做a爱过程不卡视频| 国产国语在线播放视频| 二级特黄绝大片免费视频大片| 国产精品12| 欧美a级片视频| 国产精品自拍在线观看| 91麻豆国产福利精品| 四虎影视库| 可以免费看污视频的网站| 精品视频在线看 | 四虎影视久久久免费| 免费国产在线观看| 天堂网中文字幕| 日日爽天天| 欧美激情中文字幕一区二区| 日本特黄特色aaa大片免费| 精品视频免费看| 欧美激情影院| 韩国毛片免费大片| 色综合久久久久综合体桃花网| 国产极品白嫩美女在线观看看 | 日韩免费在线观看视频| 97视频免费在线| 亚洲第一色在线| 欧美a级v片不卡在线观看| 日日夜夜婷婷| 日本乱中文字幕系列| 日本在线不卡免费视频一区| 九九精品影院| 国产成人啪精品| 国产网站免费在线观看| 国产成人啪精品| 99色视频在线| 亚洲 欧美 成人日韩| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 国产伦久视频免费观看视频| 欧美日本韩国| 99久久精品国产麻豆| 亚洲精品久久久中文字| 国产美女在线一区二区三区| 欧美激情一区二区三区视频| 日本乱中文字幕系列| 成人高清视频在线观看| 韩国毛片免费| 九九精品久久久久久久久| 欧美激情一区二区三区视频高清| 青青久热| 欧美大片aaaa一级毛片| 国产不卡福利| 成人免费观看视频| 午夜在线亚洲| 精品视频免费看| 国产一区二区精品久久| 999久久久免费精品国产牛牛| 国产伦精品一区二区三区在线观看| 国产不卡在线播放| 深夜做爰性大片中文| 日韩专区第一页| 亚洲天堂在线播放| 国产伦久视频免费观看视频| 国产网站麻豆精品视频| 欧美1卡一卡二卡三新区| 国产一区二区精品| 成人影院久久久久久影院| 韩国毛片 免费| 精品国产一区二区三区免费| 九九国产| 日韩专区第一页| 成人影视在线播放| 香蕉视频三级| 国产不卡高清在线观看视频| 日韩专区亚洲综合久久| 国产91精品一区二区| 欧美国产日韩在线| 国产视频一区二区三区四区| 色综合久久久久综合体桃花网| 久久国产一久久高清| 免费一级生活片| 国产精品免费久久| 高清一级毛片一本到免费观看| 亚洲不卡一区二区三区在线| 午夜激情视频在线播放| 午夜久久网| 亚飞与亚基在线观看| 日本在线不卡免费视频一区| 成人免费观看视频| 成人免费一级纶理片| 成人a大片在线观看| 97视频免费在线| 成人免费观看网欧美片| 日本免费看视频| 国产网站免费在线观看| 成人影院一区二区三区| 成人影院久久久久久影院| 99热精品在线| 九九久久国产精品大片| 成人免费观看网欧美片| 天天做日日干| 高清一级毛片一本到免费观看| 精品久久久久久免费影院| 精品视频免费看| 日韩在线观看免费| 国产一区二区福利久久| 免费的黄色小视频| 国产亚洲精品成人a在线| 日本免费看视频| 麻豆网站在线看| 国产美女在线观看| 日本伦理片网站| 日本在线不卡视频| 日韩男人天堂| 亚洲精品中文字幕久久久久久| 四虎影视精品永久免费网站| 亚飞与亚基在线观看| 欧美电影免费| 亚洲第一视频在线播放| 亚洲精品久久久中文字| 国产一区二区精品| 欧美激情一区二区三区在线| 日韩欧美一二三区| 欧美国产日韩精品| 国产伦精品一区三区视频| 免费一级片在线| 一级毛片视频在线观看| 天天做日日爱| 成人影视在线播放| 国产成人精品一区二区视频| 在线观看成人网 | 国产91精品一区| 青青久热| 日本伦理片网站| 欧美爱色| 欧美a级片免费看| 欧美1区| 国产亚洲精品aaa大片| 一级片片| 日本特黄特色aa大片免费| 久久国产精品只做精品| 精品久久久久久免费影院| 91麻豆国产|