淺析Vue Router中關於路由守衛的應用以及在全局導航守衛中檢查元字段

#在切換路由時,組件會被複用,不過,這也意味着組件的生命週期鉤子不會再被調用。vue

   解決辦法有兩種,1簡單地 watch (監測變化) $route 對象:react

  

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 對路由變化做出響應...
    }
  }
}

    2.使用 2.2 中引入的 beforeRouteUpdate 導航守衛:es6

const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

#全局守衛vue-router

你可使用 router.beforeEach 註冊一個全局前置守衛:數組

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})
  • to: Route: 即將要進入的目標 路由對象異步

  • from: Route: 當前導航正要離開的路由函數

  • next: Function: 必定要調用該方法來 resolve 這個鉤子測試

#全局解析守衛ui

在 2.5.0+ 你能夠用 router.beforeResolve 註冊一個全局守衛。這和 router.beforeEach 相似,區別是在導航被確認以前,同時在全部組件內守衛和異步路由組件被解析以後,解析守衛就被調用。this

#全局後置鉤子

你也能夠註冊全局後置鉤子,然而和守衛不一樣的是,這些鉤子不會接受 next 函數也不會改變導航自己:

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

#路由獨享的守衛

你能夠在路由配置上直接定義 beforeEnter 守衛

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

這些守衛與全局前置守衛的方法參數是同樣的。

#組件內的守衛

你能夠在路由組件內直接定義如下路由導航守衛:

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 由於當守衛執行前,組件實例還沒被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,可是該組件被複用時調用
    // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
    // 能夠訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 能夠訪問組件實例 `this`
  }
}

beforeRouteEnter 守衛 不能 訪問 this,由於守衛在導航確認前被調用,所以即將登場的新組件還沒被建立。

不過,你能夠經過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回調,而且把組件實例做爲回調方法的參數。

export default {
    data(){
        return {
             num: 18
        }
    },
    beforeRouteEnter(to, from, next){
        next(vm=>{
            vm.num=22;
        })
    }
}

注意 beforeRouteEnter 是支持給 next 傳遞迴調的惟一守衛。對於 beforeRouteUpdate 和 beforeRouteLeave 來講,this 已經可用了,因此不支持傳遞迴調,由於沒有必要了

#完整的導航解析流程

1.導航被觸發。
2.在失活的組件裏調用離開守衛。
3.調用全局的 beforeEach 守衛。
4.在重用的組件裏調用 beforeRouteUpdate 守衛 (2.2+)。
5.在路由配置裏調用 beforeEnter。
6.解析異步路由組件。
7.在被激活的組件裏調用 beforeRouteEnter。
8.調用全局的 beforeResolve 守衛 (2.5+)。
9.導航被確認。
10.調用全局的 afterEach 鉤子。
11.觸發 DOM 更新。
12.用建立好的實例調用 beforeRouteEnter 守衛中傳給 next 的回調函數。

#在全局導航守衛中檢查元字段

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    //若是路由中有meta的requireAuth,且爲true,就不進行登陸驗證,不然進行登陸驗證
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 確保必定要調用 next()
  }
})

一個路由匹配到的全部路由記錄會暴露爲 $route 對象 (還有在導航守衛中的路由對象) 的 $route.matched 數組。所以,咱們須要遍歷 $route.matched 來檢查路由記錄中的 meta 字段。

  注:一、meta 字段就是路由元信息字段,requiresAuth 是本身起的字段名稱,用來標記這個路由信息是否須要檢測,true 表示要檢測,false 表示不須要檢測(這個名稱隨便起,好比我本身的就起的 requiresId,建議起個有意義的名稱)

  二、if (to.matched.some(record => record.meta.requiresAuth) ),若是對這類寫法不熟悉,能夠去看看es6的箭頭函數,這句話就是返回遍歷的某個路由對象,咱們定義爲爲record,檢測這個對象是否擁有meta這個對象,若是有meta這個對象,檢測它的meta對象是否是有requiresAuth這個屬性,且爲true,若是知足上述條件,就肯定了是這個/foo/bar路由。

  三、some() 方法測試數組中的某些元素是否經過了指定函數的測試。語法:arr.some(callback[, thisArg]);

    some 爲數組中的每個元素執行一次 callback 函數,直到找到一個使得 callback 返回一個「真值」(便可轉換爲布爾值 true 的值)。若是找到了這樣一個值,some 將會當即返回 true。不然,some 返回 false。callback 只會在那些」有值「的索引上被調用,不會在那些被刪除或歷來未被賦值的索引上調用。

     callback 被調用時傳入三個參數:元素的值,元素的索引,被遍歷的數組。

  四、vue-router路由元信息說白了就是經過meta對象中的一些屬性來判斷當前路由是否須要進一步處理,若是須要處理,按照本身想要的效果進行處理便可!

相關文章
相關標籤/搜索