1. 程式人生 > >vue2路由導航守衛(鉤子函式)

vue2路由導航守衛(鉤子函式)

官方:vue-router 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全域性的, 單個路由獨享的, 或者元件級的。

所謂的Vue路由導航守衛,也就是我們常說的生命週期鉤子函式,鉤子函式的意思就是在特定的時刻,Vue會自動觸發這個方法,我們可以通過這些個鉤子函式,實現一些功能,比如,某些頁面需要登入後才可以訪問,某些頁面需要使用者達到什麼等級才可以訪問,又或者是跳轉頁面後修改一些資訊等等,我們就可以通過路由導航守衛來攔截並做相應的處理

全域性守衛:

掛載在router例項上

  • 全域性前置鉤子

注意:引數或查詢的改變並不會觸發進入/離開的導航守衛。你可以通過觀察 $route 物件來應對這些變化,或使用 beforeRouteUpdate 的元件內守衛。

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

        //to: Route: 即將要進入的目標 路由物件

        //from: Route: 當前導航正要離開的路由

        //next: Function:如果你想要進入下一個導航,就必須要呼叫next()方法,否則不會進入下一個導航
})

官方對於next()的解釋:

  • next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
  • next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是使用者手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
  • next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向 next 傳遞任意位置物件,且允許設定諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
  • next(error): (2.4.0+) 如果傳入 next 的引數是一個 Error 例項,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回撥。

看個小示例:

router.beforeEach((to,from,next)=>{
  if(to.matched.some((item)=>item.meta.login)){
    console.log(to)
    //router.app就是我們的根例項
    let info = router.app.$local.fetch('miaov')
    // console.log(info)

    if(info.login){
      next()
    }else{
      router.push({
        path:'/login'
      })
    }
  }else{
    next()
  }
})
  • 全域性後置鉤子:

注意:這些鉤子不會接受next函式,也不會改變導航本身

router.afterEach((to,from)=>{


})

區域性鉤子函式

區域性鉤子函式可以寫在兩個地方,一個是寫在元件對應的路由配置中,一個是直接寫在元件中

路由獨享的守衛:

可以在路由配置上直接定義beforeEnter守衛:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
        //引數和前置守衛的引數含義一樣
      }
    }
  ]
})

元件內的守衛:

  1. beforeRouteEnter
  2. beforeRouteUpdata(2.2新增)
  3. beforeRouteLeave
beforeRouteEnter(to,from,next){
        
        //在渲染該元件的對應路由被confirm前呼叫
        //不能獲取元件例項“this”
        //因為當守衛執行前,元件例項還沒被建立

}

beforeRouteEnter 守衛不能訪問this,因為守衛在導航確認前被呼叫,因此即將登場的新組建還沒被建立

可以通過傳一個回撥給next來訪問元件例項。在導航被確認的時候執行回撥,並且把元件例項作為回撥方法的引數

  export default {
    data(){
      return {
          flag: ''
      }
    },
    watch: {
      $route(){
        this.flag = flags[this.$route.path.slice(1)]
      }
    },
    beforeRouteEnter(to, from, next){//複用的,不會重新走鉤子函式, 所以需要watch監控路由資訊物件
      next((vm) => {
        vm.flag = flags[to.path.slice(1)]
      })
    },
    components: {
      headerNav: Header

      /*(resolve) => {
        setTimeout(() => {
          resolve(require('@/components/header'))
        }, 2000)
      }*/
    }
  }

 注意:beforeRouteEnter是支援給next傳遞迴調的唯一守衛。對於beforeRouteUpdate和beforeRouteLeave來說
this已經可用了,所以不支援傳遞迴調

beforeRouteUpdate(to,from,next){
        //在當前路由改變,但是該元件被複用時呼叫
        //可以訪問元件例項this
        
}

這個函式應用場景比較特殊一點,當元件中有子導航時,我們就可以在這個父元件中使用這個方法來監控子路由的跳轉了,然後再父元件中做出相應的處理,除了使用beforeRouteUpdate()函式外,我們還可以在父元件中使用watch來監控路由的變化,效果是差不多的,嗯,根據實際情況來判斷該使用哪一種方式處理

  看個簡單的小例子:

export default {
      data(){
       return{
         test:0
       }
      },
   //方法一 
      watch:{
        $route(){
          this.test++
        }
      },
      beforeRouteEnter(to,from,next){
        //this是個undefined,因為元件的例項還沒有建立
        next((vm)=>{
          vm.test++
        });//next中可以接收一個回撥函式
      },
   /*  方法二
      // beforeRouteUpdate(to,from,next){
      //   this.test++
      //   next();
      // },
   */
      beforeRouteLeave(to,from,next){
next();
      },
        name: "about"
    }
beforeRouteLeave(to,from,next){
        //導航離開該元件的對應路由時呼叫
        //可以訪問元件例項this
}

離開守衛通常用來禁止使用者在還未儲存修改前突然離開。該導航可以通過next(false)來取消