国产精品美女久久久浪潮AV,国产精品三级一二三区,久久精品国产一区二区小说 ,依依成人影视国产精品,全部无卡免费的毛片在线看,日本一区二区三深夜不卡,国产精品女同一区二区久久,国产精品夜色一区二区三区

        vue-router 導(dǎo)航守衛(wèi)中 next 控制實(shí)現(xiàn)

        2020-5-14    seo達(dá)人

        使用 vue-router 的導(dǎo)航守衛(wèi)鉤子函數(shù),某些鉤子函數(shù)可以讓開發(fā)者根據(jù)業(yè)務(wù)邏輯,控制是否進(jìn)行下一步,或者進(jìn)入到指定的路由。


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


        // 全局導(dǎo)航守衛(wèi)

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

         if('no login'){

           next('/login')

         }else if('admin') {

           next('/admin')

         }else {

           next()

         }

        })


        // 路由配置鉤子函數(shù)

        {

         path: '',

         component: component,

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

           next()

         }

        }


        // 組件中配置鉤子函數(shù)

        {

         template: '',

         beforeRouteEnter(to, from, next) {

           next()

         }

        }

        調(diào)用 next,意味著繼續(xù)進(jìn)行下面的流程;不調(diào)用,則直接終止,導(dǎo)致路由中設(shè)置的組件無法渲染,會(huì)出現(xiàn)頁面一片空白的現(xiàn)象。


        鉤子函數(shù)有不同的作用,例如 beforEach,afterEach,beforeEnter,beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave,針對這些注冊的鉤子函數(shù),要依次進(jìn)行執(zhí)行,并且在必要環(huán)節(jié)有控制權(quán)決定是否繼續(xù)進(jìn)入到下一個(gè)鉤子函數(shù)中。


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


        精簡源碼核心功能

        總結(jié)下核心點(diǎn):鉤子函數(shù)注冊的回調(diào)函數(shù),能順序執(zhí)行,同時(shí)會(huì)將控制權(quán)交給開發(fā)者。


        先來一個(gè)能夠注冊回調(diào)函數(shù)的類:


        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 來注冊必要的回調(diào)函數(shù)。


        抽象出一個(gè) registerHook 公共方法,作用:


        注冊回調(diào)函數(shù)

        返回的函數(shù),可以取消注冊的回調(diào)函數(shù)

        使用一下:


        const router = new VueRouter()


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

         console.log('beforEach');

         next()

        })

        // 取消注冊的函數(shù)

        beforEach()

        以上的回調(diào)函數(shù)會(huì)被取消,意味著不會(huì)執(zhí)行了。



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

         console.log('beforEach');

         next()

        })


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

         console.log('beforeEnter');

         next()

        })


        router.afterEach(() => {

         console.log('afterEach');

        })

        以上注冊的鉤子函數(shù)會(huì)依次執(zhí)行。beforEach 和 beforeEnter 的回調(diào)接收內(nèi)部傳來的參數(shù),同時(shí)通過調(diào)用 next 可繼續(xù)走下面的回調(diào)函數(shù),如果不調(diào)用,則直接被終止了。

        最后一個(gè) afterEach 在上面的回調(diào)函數(shù)都執(zhí)行后,才被執(zhí)行,且不接收任何參數(shù)。


        先來實(shí)現(xiàn)依次執(zhí)行,這是最簡單的方式,在類中增加 run 方法,手動(dòng)調(diào)用:



        class VueRouter {

         // ... 其他省略,增加 run 函數(shù)


         run(){

           // 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中

           let queue = [].concat(

             this.beforeHooks,

             this.afterHooks

           )

           

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

             if(queue(i)) {

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

             }

           }

         }

        }


        // 手動(dòng)調(diào)用


        router.run()

        打印:


        'beforEach'

        'beforeEnter'

        上面把要依次執(zhí)行的回調(diào)函數(shù)聚合在一個(gè)隊(duì)列中執(zhí)行,并傳入必要的參數(shù),但這樣開發(fā)者不能控制是否進(jìn)行下一步,即便不執(zhí)行 next 函數(shù),依然會(huì)依次執(zhí)行完隊(duì)列的函數(shù)。


        改進(jìn)一下:


        class VueRouter {

         // ... 其他省略,增加 run 函數(shù)


         run(){

           // 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中

           let queue = [].concat(

             this.beforeHooks,

             this.afterHooks

           )

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

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

              console.log('調(diào)用結(jié)束');

             })

           })

         }

        }


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

         console.log('beforEach');

         // next()

        })


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

         console.log('beforeEnter');

         next()

        })

        傳入的 next 函數(shù)會(huì)有調(diào)用下一個(gè)回調(diào)函數(shù)的行為,把控制權(quán)交給了開發(fā)者,調(diào)用了 next 函數(shù)會(huì)繼續(xù)執(zhí)行下一個(gè)回調(diào)函數(shù);不調(diào)用 next 函數(shù),則終止了隊(duì)列的執(zhí)行,所以打印結(jié)果是:


        'beforEach'

        上面實(shí)現(xiàn)有個(gè)弊端,代碼不夠靈活,手動(dòng)一個(gè)個(gè)調(diào)用,在真實(shí)場景中無法確定注冊了多少個(gè)回調(diào)函數(shù),所以需要繼續(xù)抽象成一個(gè)功能更強(qiáng)的方法:


        function runQueue (queue, fn, cb) {

         const step = index => {

           // 隊(duì)列執(zhí)行結(jié)束了

           if (index >= queue.length) {

             cb()

           } else {

             // 隊(duì)列有值

             if (queue[index]) {

               // 傳入隊(duì)列中回調(diào),做一些必要的操作,第二個(gè)參數(shù)是為了進(jìn)行下一個(gè)回調(diào)函數(shù)

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

                 step(index + 1)

               })

             } else {

               step(index + 1)

             }

           }

         }

         // 初次調(diào)用,從第一個(gè)開始

         step(0)

        }

        runQueue 就是執(zhí)行隊(duì)列的通用方法。


        第一個(gè)參數(shù)為回調(diào)函數(shù)隊(duì)列, 會(huì)依次取出來;

        第二個(gè)參數(shù)是函數(shù),它接受隊(duì)列中的函數(shù),進(jìn)行一些其他處理;并能進(jìn)行下個(gè)回調(diào)函數(shù)的執(zhí)行;

        第三個(gè)參數(shù)是隊(duì)列執(zhí)行結(jié)束后調(diào)用。

        知道了這個(gè)函數(shù)的含義,來使用一下:



        class VueRouter {

         // ... 其他省略,增加 run 函數(shù)


         run(){

           // 把需要依次執(zhí)行的回調(diào)存放在一個(gè)隊(duì)列中

           let queue = [].concat(

             this.beforeHooks,

             this.beforeEnterHooks

           )


           // 接收回到函數(shù),和進(jìn)行下一個(gè)的執(zhí)行函數(shù)

           const iterator = (hook, next) => {

             // 傳給回調(diào)函數(shù)的參數(shù),第三個(gè)參數(shù)是函數(shù),交給開發(fā)者調(diào)用,調(diào)用后進(jìn)行下一個(gè)

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

               console.log('執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息');

               next()

             })

           }


           runQueue(queue, iterator, () => {


             console.log('執(zhí)行結(jié)束');

             // 執(zhí)行 afterEach 中的回調(diào)函數(shù)

             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();

        從上面代碼可以看出來,每次把隊(duì)列 queue 中的回調(diào)函數(shù)傳給 iterator , 用 hook 接收,并調(diào)用。

        傳給 hook 必要的參數(shù),尤其是第三個(gè)參數(shù),開發(fā)者在注冊的回調(diào)函數(shù)中調(diào)用,來控制進(jìn)行下一步。

        在隊(duì)列執(zhí)行完畢后,依次執(zhí)行 afterHooks 的回調(diào)函數(shù),不傳入任何參數(shù)。


        所以打印結(jié)果為:


        beforEach

        執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息

        beforeEnter

        執(zhí)行下一個(gè)回調(diào)時(shí),處理一些相關(guān)信息

        執(zhí)行結(jié)束

        afterEach

        以上實(shí)現(xiàn)的非常巧妙,再看 Vue-router 源碼這塊的實(shí)現(xiàn)方式,相信你會(huì)豁然開朗。

        日歷

        鏈接

        個(gè)人資料

        存檔

        主站蜘蛛池模板: 国产高清在线精品一区二区三区| 人妻夜夜爽爽88888视频| 亚洲免费视频免在线观看| 亚洲精品字幕| 神马影院888不卡院| 亚洲成av人片在线观看无码| 亚洲乱妇熟女爽到高潮的片| а√天堂8资源中文在线| 樱桃视频大全免费高清版观看| 内射极品少妇xxxxxhd| 最近中文字幕免费手机版| 亚洲精品久久片久久久久| 18禁裸乳无遮挡啪啪无码免费| 一面膜胸口一面膜下免费| 亚洲无线码一区二区三区| 一二三四在线观看免费中文 | 亚洲精品乱码久久久久久不卡| 米奇7777狠狠狠狠视频影院| 在线天堂资源www在线| 狠狠色丁香婷婷综合尤物 | 精品一区二区成人精品| 欧美交换配乱吟粗大视频| 日本高清一区免费中文视频| 亚洲国产v高清在线观看| 一个人在线观看免费完整版 | 暖暖 在线 日本 免费 中文| 免费+无码+国产在线观看| 资兴市| 好姑娘3完整版在线观看高清| 天天爽天天爽夜夜爽毛片| 中文亚洲av片不卡在线观看| 天全县| 图片| 无码成人一区二区三区| 国产精品美女久久久久av超清| 国产高清在线a视频大全| 久久婷婷是五月综合色| 99久久精品国产成人综合| 欧美粗大猛烈老熟妇| 丰满少妇被猛烈进入无码| 亚洲午夜高清国产拍|