vue-router 提供的導航鉤子主要用來攔截導航,讓它完成跳轉或取消。有多種方式能夠在路由導航發生時執行鉤子:全局的, 單個路由獨享的, 或者組件級的。vue
全局鉤子vue-router
你可使用 router.beforeEach 註冊一個全局的 before 鉤子:數組
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
當一個導航觸發時,全局的 before 鉤子按照建立順序調用。鉤子是異步解析執行,此時導航在全部鉤子 resolve 完以前一直處於 等待中。瀏覽器
每一個鉤子方法接收三個參數:異步
to: Route: 即將要進入的目標 路由對象 from: Route: 當前導航正要離開的路由 next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。 next(): 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是 confirmed (確認的)。 next(false): 中斷當前的導航。若是瀏覽器的 URL 改變了(多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。 next('/') 或者 next({ path: '/' }): 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。
確保要調用 next 方法,不然鉤子就不會被 resolved。ui
一樣能夠註冊一個全局的 after 鉤子,不過它不像 before 鉤子那樣,after 鉤子沒有 next 方法,不能改變導航:this
router.afterEach(route => { // ... })
你能夠在路由配置上直接定義 beforeEnter 鉤子:code
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
這些鉤子與全局 before 鉤子的方法參數是同樣的。
組件內的鉤子component
最後,你能夠在路由組件內直接定義如下路由導航鉤子:router
beforeRouteEnter beforeRouteUpdate (2.2 新增) beforeRouteLeave 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來訪問組件實例。在導航被確認的時候執行回調,而且把組件實例做爲回調方法的參數。
beforeRouteEnter (to, from, next) { next(vm => { // 經過 `vm` 訪問組件實例 }) }
你能夠 在 beforeRouteLeave 中直接訪問 this。這個 leave 鉤子一般用來禁止用戶在還未保存修改前忽然離開。能夠經過 next(false) 來取消導航。
定義路由的時候能夠配置 meta 字段:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar, // a meta field meta: { requiresAuth: true } } ] } ] })
那麼如何訪問這個 meta 字段呢?
首先,咱們稱呼 routes 配置中的每一個路由對象爲 路由記錄。路由記錄能夠是嵌套的,所以,當一個路由匹配成功後,他可能匹配多個路由記錄
例如,根據上面的路由配置,/foo/bar 這個 URL 將會匹配父路由記錄以及子路由記錄。
一個路由匹配到的全部路由記錄會暴露爲 $route 對象(還有在導航鉤子中的 route 對象)的 $route.matched 數組。所以,咱們須要遍歷 $route.matched 來檢查路由記錄中的 meta 字段。
下面例子展現在全局導航鉤子中檢查 meta 字段:
router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, redirect to login page. if (!auth.loggedIn()) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } else { next() // 確保必定要調用 next() } })