国产精品爱久久久久久久小说,女人扒开腿让男人桶到爽 ,亚洲欧美国产双大乳头,国产成人精品综合久久久久,国产精品制服丝袜无码,免费无码精品黄av电影,黑色丝袜无码中中文字幕,乱熟女高潮一区二区在线

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

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

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


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


    // 全局導(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ù)進行下面的流程;不調(diào)用,則直接終止,導(dǎo)致路由中設(shè)置的組件無法渲染,會出現(xiàn)頁面一片空白的現(xiàn)象。


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


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


    精簡源碼核心功能

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


    先來一個能夠注冊回調(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ù)。


    抽象出一個 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ù)會被取消,意味著不會執(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ù)會依次執(zhí)行。beforEach 和 beforeEnter 的回調(diào)接收內(nèi)部傳來的參數(shù),同時通過調(diào)用 next 可繼續(xù)走下面的回調(diào)函數(shù),如果不調(diào)用,則直接被終止了。

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


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



    class VueRouter {

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


     run(){

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

       let queue = [].concat(

         this.beforeHooks,

         this.afterHooks

       )

       

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

         if(queue(i)) {

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

         }

       }

     }

    }


    // 手動調(diào)用


    router.run()

    打印:


    'beforEach'

    'beforeEnter'

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


    改進一下:


    class VueRouter {

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


     run(){

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

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


    'beforEach'

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


    function runQueue (queue, fn, cb) {

     const step = index => {

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

       if (index >= queue.length) {

         cb()

       } else {

         // 隊列有值

         if (queue[index]) {

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

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

             step(index + 1)

           })

         } else {

           step(index + 1)

         }

       }

     }

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

     step(0)

    }

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


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

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

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

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



    class VueRouter {

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


     run(){

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

       let queue = [].concat(

         this.beforeHooks,

         this.beforeEnterHooks

       )


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

       const iterator = (hook, next) => {

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

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

           console.log('執(zhí)行下一個回調(diào)時,處理一些相關(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();

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

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

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


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


    beforEach

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

    beforeEnter

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

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

    afterEach

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

    日歷

    鏈接

    個人資料

    存檔

    主站蜘蛛池模板: 男女18禁啪啪无遮挡激烈网站| www.污污| 亚洲免费观看av| 亚洲中文字幕无码mv| 国产精品免费高清在线观看| 欧美日韩国产精品一区| 欧美天天性影院| 天天色影网| 成人午夜精品无码一区二区三区| 成人h动漫精品一区二区| 九九热免费精品在线视频| 国产一区二区三区久久精品| 少妇高潮潮喷到猛进猛出小说| 亚洲欧美校园春色| 欧美另类高清zo欧美| 免费无码va一区二区三区| 亚洲视频欧美视频| 成人一级黄色| 人人爽人人爽人人片av| 男女啪啪抽搐高潮动态图| 精品三级| 少妇久久久久久| 色资源av中文无码先锋| 丰满少妇被猛烈进入试看| 人妻少妇被猛烈进入中文字幕| 国产按摩一区二区三区| 亚洲加勒比久久88色综合| 日韩欧美亚洲中文乱码| 国产一区二区视频在线| 天天插天天干天天操| 刺激性视频黄页| 7777久久久国产精品消防器材| 一区二区在线看| 日韩在线播放一区| 美日韩av一区二区三区| 成人福利国产午夜av免费不卡在线| 91视频网址| 成年人视频在线观看免费| 精品视频不卡免费观看| 岛国av动作片在线观看| 中文字幕漂亮人妻熟睡中被公侵犯|