快速瞭解vue路由

創建一個路由實例的配置選項

使用 new Router 創建了一個新的路由實例,其配置項說明:
mode:路由模式,默認值 ‘hash’ 使用井號( # )作路由,值 ‘history’ 可利用 History API 來完成頁面跳轉且無須重新加載;
routes:具體的路由配置列表,用到的配置項說明:
path:路由的路徑;
name:路由的名稱;
component:對應的視圖組件;
通過注入路由器,我們可以在任何組件內通過 this.routerthis.router 訪問路由器,也可以通過 this.route 訪問當前路由
動態路由參數匹配

模式 匹配路徑 $route.params
/user/:username /user/evan { username: ‘evan’ }
/user/:username/post/:post_id /user/evan/post/123 { username: ‘evan’, post_id: ‘123’ }

除了 route.paramsroute.params 外,route 對象還提供了其它有用的信息,例如,route.query(URL)route.query (如果 URL 中有查詢參數)、route.hash 等等

相應路由參數的變化

當使用路由參數時,例如從 /user/foo 導航到 /user/bar,原來的組件實例會被複用。因爲兩個路由都渲染同個組件,比起銷燬再創建,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用
複用組件時,想對路由參數的變化作出響應的話,你可以簡單地 watch (監測變化) $route 對象

const User1 = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 對路由變化作出響應...
    }
  }
}
//或者使用
const User2 = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}
路由匹配優先級

有時候,同一個路徑可以匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高
當使用通配符路由時,請確保路由的順序是正確的,也就是說含有通配符的路由應該放在最後

嵌套路由
const routes = [
  {
    path:'/user/:id',
    component:()=>import('@/views/user/User'),
    children:[
      {
        //默認子路由
        // UserHome 會被渲染在 User 的 <router-view> 中
        path:'',
        name:'UserHome',
        component:()=>import('@/views/user/UserHome'),
      },
      {
        // 當 /user/:id/profile 匹配成功,
        // UserProfile 會被渲染在 User 的 <router-view> 中
        path:'profile',
        name:'UserProfile',
        component:()=>import('@/views/user/UserProfile'),
      }
    ],
  }
];
編程式的導航
聲明式 編程式
<router-link :to="…"> router.push(…)

在 Vue 實例內部,你可以通過 router調this.router 訪問路由實例。因此你可以調用 this.router.push
router.push這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前的 URL。

// 字符串
router.push('home')

// 對象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 會被忽略,同樣的規則也適用於 router-link 組件的 to 屬性
注意: 如果目的地和當前路由相同,只有參數發生了改變 (比如從一個用戶資料到另一個 /users/1 -> /users/2),你需要使用 beforeRouteUpdate 來響應這個變化 (比如抓取用戶信息)

router.replace 跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄

聲明式 編程式
<router-link :to="…" replace> router.replace(…)

router.go(n)這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似 window.history.go(n)

命名路由
const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',
      component: User
    }
  ]
})

<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

router.push({ name: 'user', params: { userId: 123 }})
重定向和路由別名
const router = new VueRouter({
  routes: [
    { 
      path: '/a', 
      redirect: '/b'
    }
  ]
})
const router2 = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})
//別名的功能讓你可以自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構
路由組件傳參

在組件中使用 $route 會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性
通過 props 解耦,如果 props 被設置爲 true,route.params 將會被設置爲組件屬性

導航守衛

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

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

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

to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 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() 註冊過的回調。
確保要調用 next 方法,否則鉤子就不會被 resolved

全局後置鉤子

你也可以註冊全局後置鉤子,然而和守衛不同的是,這些鉤子不會接受 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`
  }
}
路由元信息
路由過渡動效
數據獲取

有時候,進入某個路由後,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現:
導航完成之後獲取:先完成導航,然後在接下來的組件生命週期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。
導航完成之前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功後執行導航。
從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。

滾動行爲
// 指定滾動行爲
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      // 有錨點時,滾動到錨點
      return { selector: to.hash }
    } else if (savedPosition) {
      // 有保存位置時,滾動到保存位置
      return savedPosition
    } else {
      // 默認滾動到頁面頂部
      return { x: 0, y: 0 }
    }
  }
路由懶加載
導航守衛

導航守衛分爲全局導航守衛和路由導航守衛

router.beforeEach((to, from, next) => {
  /* must call `next` */
})

router.beforeResolve((to, from, next) => {
  /* must call `next` */
})

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

//組件內的守衛
beforeRouteEnter

beforeRouteUpdate

beforeRouteLeave
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章