• <abbr id="chdyf"></abbr>
    <ruby id="chdyf"><acronym id="chdyf"><meter id="chdyf"></meter></acronym></ruby>
    <bdo id="chdyf"></bdo>
    <dfn id="chdyf"><menu id="chdyf"></menu></dfn>
    1. <menuitem id="chdyf"></menuitem><strong id="chdyf"><menu id="chdyf"></menu></strong>

      <rt id="chdyf"><menu id="chdyf"></menu></rt>
      成人小说一区二区三区,伊人精品成人久久综合全集观看,久久HEZYO色综合,中文字幕精品人妻熟女,影音先锋成人网站,我要看免费一级毛片,中国女人做爰A片,中文字幕av久久爽Av

      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.wtxcl.cn

      存檔

      主站蜘蛛池模板: 久久6| 精品视频在线观看| 久久国产欧美日韩精品图片| 红河县| 丁香五月激情图片| 福利导航页| 人妻丰满熟av无码区hd| 亚洲男人AV香蕉爽爽爽爽| 波多野结衣精品1区2区3区| 桃色91| 国产老熟女伦老熟妇露脸| 一二三区中文字幕| 国产精品玖玖玖在线资源| 免费黄色片成人国产精品| 亚洲精品美女久久久久99| 动漫av在线| 无码人妻精品一区二区三区温州| A片丝袜| 国产午夜无码视频免费网站| 色玖玖| av片免费播放| AV在线无码| 朝鲜女人大白屁股ASS孕交| 67194欧洲女人| 亚洲AV第二区国产精品| 武汉市| 性俄罗斯牲交XXXXX视频| 亚洲最大三级网站| 久久影音先锋| 子洲县| 老湿机看片新入口福利| 亚洲网友自拍| 夜夜嗨av色一区二区不卡| 东京热无码人妻中文字幕| 国产真实乱子伦偷精品| 97超碰碰| 偷拍99| 91视频入口| 亚洲AV永久无码天堂网一线| 无码人妻精品一区二区三区温州| 国产成人AA|