vue Router——進階篇

vue Router——基礎篇html

1.導航守衛

正如其名,vue-router 提供的導航守衛主要用來經過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程當中:全局的, 單個路由獨享的, 或者組件級的。前端

記住參數或查詢的改變並不會觸發進入/離開的導航守衛。你能夠經過觀察 $route 對象來應對這些變化,或使用 beforeRouteUpdate 的組件內守衛vue

全局前置守衛

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

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

當一個導航觸發時,全局前置守衛按照建立順序調用。守衛是異步解析執行,此時導航在全部守衛 resolve 完以前一直處於 等待中webpack

每一個守衛方法接收三個參數:web

  • to: Route: 即將要進入的目標 路由對象
  • from: Route: 當前導航正要離開的路由
  • next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。
    • next(): 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是 confirmed (確認的)
    • next(false): 中斷當前的導航。若是瀏覽器的 URL 改變了 (多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
    • next('/') 或者 next({ path: '/' }): 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。你能夠向 next 傳遞任意位置對象,且容許設置諸如 replace: truename: 'home' 之類的選項以及任何用在 router-linkto prop 或 router.push 中的選項。
    • next(error): (2.4.0+) 若是傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回調。

確保要調用 next 方法,不然鉤子就不會被 resolved

舉個例子vue-router

router.beforeEach((to, from, next) => {
  if(to.name === 'One'){
    next('Two')
  }
  next()
})

當咱們訪問api

http://localhost:8080/#/One

時,就會跳到數組

http://localhost:8080/#/Two

全局解析守衛

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

router.beforeEach((to, from, next) => {
  if(to.name === 'One'){
    next('Two')
  }
  next()
})

router.beforeResolve((to, from, next) => {
  if(to.name === 'Two'){
    next('Three')
  }
  next()
})

當咱們訪問異步

http://localhost:8080/#/One

時,就會跳到

http://localhost:8080/#/Two

而後再跳到

http://localhost:8080/#/Three

全局後置鉤子

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

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

路由獨享的守衛

路由

{
  path: '/One',
  name: 'One',
  component: One,
  beforeEnter: (to, from, next) => {
    if(to.name === 'One'){
      next('Two')
    }
    next()
  }
}

當咱們訪問

http://localhost:8080/#/One

時,就會跳到

http://localhost:8080/#/Two

組件內的守衛

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
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` 訪問組件實例
  })
}

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

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}
beforeRouteLeave
beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

這個離開守衛一般用來禁止用戶在還未保存修改前忽然離開。該導航能夠經過 next(false) 來取消

完整的導航解析流程!!!

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

2.路由元信息

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

咱們稱 routes 配置中的每一個路由對象爲一個路由記錄。路由記錄能夠是嵌套的,所以,當一個路由匹配成功後,他可能匹配多個路由記錄

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

在舉個栗子

router.beforeEach((to, from, next) => {
  //判斷路由記錄是否須要驗證登陸
  if (to.matched.some(record => record.meta.requiresAuth)) {
    //  本身定義的判斷登陸的方法
    let isLogin = getLoginStatus()
    if (!isLogin()) {
      next({
        // 跳轉到登陸頁
        path: '/login',
        // 登陸頁須要知道從哪跳過來的,方便登陸成功後回到原頁面
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 確保必定要調用 next()
  }
})

注意!!!

next必定要執行否則鉤子函數不會resolved。

3.滾動行爲

使用前端路由,當切換到新路由時,想要頁面滾到頂部,或者是保持原先的滾動位置,就像從新加載頁面那樣。 vue-router 能作到,並且更好,它讓你能夠自定義路由切換時頁面如何滾動。

注意: 這個功能只在支持 history.pushState 的瀏覽器中可用。

當建立一個 Router 實例,你能夠提供一個 scrollBehavior 方法

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    if(to.name === 'BookDetails'){
      return { x: 0, y: 0 }
    }
  }
})

scrollBehavior 方法接收 tofrom 路由對象。第三個參數 savedPosition 當且僅當 popstate 導航 (經過瀏覽器的 前進/後退 按鈕觸發) 時纔可用

當咱們訪問BookDetails路由的時候,就會回到頂部

固然還有好多,就不一一介紹了,能夠看這裏

4.路由懶加載

懶加載也叫延遲加載,即在須要的時候進行加載,隨用隨載。在單頁應用中,若是沒有應用懶加載,運用webpack打包後的文件將會異常的大,形成進入首頁時,須要加載的內容過多,延時過長,不利於用戶體驗,而運用懶加載則能夠將頁面進行劃分,須要的時候加載頁面,能夠有效的分擔首頁所承擔的加載壓力,減小首頁加載用時。

按需加載

{
  path: '/Fruits',
  name: 'Fruits',
  component: require('@/components/Fruits')  // 非按需加載
}

{
  path: '/Fruits',
  name: 'Fruits',
  component: require(['@/components/Fruits'], resolve)  // 按需加載
}

按需加載會在頁面第一次請求的時候,把相關路由組件塊的js添加上;非按需加載則會把全部的路由組件塊的js包打在一塊兒

import()

  • 推薦使用這種方式(須要webpack > 2.4)
  • webpack官方文檔:webpack中使用import() vue官方文檔:路由懶加載使用import()
const Fruits = () => import('@/components/Fruits')
{
  path: '/Fruits',
  name: 'Fruits',
  component: Fruits
}

或者

{
  path: '/Fruits',
  name: 'Fruits',
  component: () => import('@/components/Fruits')
}

把組件按組分塊

有時候咱們想把某個路由下的全部組件都打包在同個異步塊 (chunk) 中。只須要使用 命名 chunk,一個特殊的註釋語法來提供 chunk name (須要 Webpack > 2.4)

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中

Vue Router

Vue Router Api

相關文章
相關標籤/搜索