Vue-Router學習筆記

weixin_34402408發表於2018-10-23

一、基礎

1. 介紹

Vue Router 是 Vue.js官方的路由管理器。是我們使用Vue構建的SPA(單頁應用 Single Page Application)的路徑管理器。本質上就是建立頁面Url與元件之間的對映關係

2. 基本使用

2.1 安裝

npm install vue-router -S
複製程式碼

2.2 在入口檔案中引入並配置

// 專案入口檔案main.js

// 1. 引入vue、vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'

// 2. 引入專案元件
import App from './App.vue'
import Home from './components/Home.vue'
import Hello from './components/Hello.vue'

// 3. 呼叫vue-router
Vue.use(VueRouter)

// 4. 建立router例項,定義路由配置
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    },
    {
      path: '/hello',
      component: Hello
    },
    {
      path: '/',
      // 根目錄重定向至 /home
      redirect: '/home'
    }
  ]
})

// 5. 建立、掛載根例項並注入路由
new Vue({
  render: h => h(App),
  router
}).$mount('#app')
複製程式碼

2.3 在App.vue中插入導航及檢視渲染標籤

<!-- App.vue -->
<template>
    <div>
      <div class="nav">
        <router-link to="/home">Home</router-link>
        <router-link to="/hello">Hello</router-link>
      </div>
      <!-- 路由渲染出口 -->
      <router-view></router-view>
    </div>
</template>
複製程式碼

二、動態路由匹配(相當於路由傳參)

使用場景

某個模式下匹配到的所有路由,都對映到同一元件。例如不同使用者的個人資訊頁面,或者不同文章頁面等。

要點概括

  1. 定義路由路徑時使用動態引數(以冒號開頭):path: '/ComponentA/:xxx'
  2. ComponentA中通過this.$route.params.xxx獲取引數
// Main.js 
// 定義路由配置時路徑使用動態引數(以冒號開頭即可)
const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User
    }
  ]
})

// User.vue
// 路由匹配成功時,引數會被設定到this.$route.params中
export default {
  ...
  // 元件內的路由導航守衛
  beforeRouteEnter (to, from, next) {
    // 在渲染該元件的對應路由被 confirm 前呼叫
    // 不!能!獲取元件例項 `this`,通過傳回撥給 next並把元件例項作為回撥方法的引數來訪問元件例項
    next(vm => {
      vm.getUserInfo(vm.$route.params.id)
    })
  },
  // 元件內的路由導航守衛
  beforeRouteUpdate(to, from, next) {
    // 在當前路由改變,但是該元件被複用時呼叫
    this.getUserInfo(this.$route.params.id)
  }
}

// User.vue
// 在模板插值語法中,通過 $route.params.id 獲取路徑引數
<template>
  <div>
    <p>使用者ID:{{$route.params.id}}</p>
    <p>使用者名稱:{{userInfo.name}}</p>
  </div>
</template>
複製程式碼

檢視線上例子

三、巢狀路由(多級路由)

使用場景

應用中元件存在多層巢狀組合的關係。

要點概括

  1. 路由配置時使用children欄位,配置類似routes
  2. 在渲染元件中插入巢狀的導航<router-link>及渲染出口<router-view>標籤
// Main.js 
// 定義路由配置時路徑使用children欄位,配置類似routes
const router = new VueRouter({
  routes: [
    {
      path: '/user',
      component: User,
      children: [
        {path: 'info', component: UserInfo},
        {path: 'posts', component: UserPosts}
      ]
    }
  ]
})

// User.vue
// 在模板中,插入巢狀的<router-link>及<router-view>
<template>
  <div>
    <p>使用者User元件</p>
    <p>
      <router-link to="/user/info">使用者資訊</router-link>
      <router-link to="/user/posts">使用者文章</router-link>
    </p>
    <router-view></router-view>
  </div>
</template>
複製程式碼

檢視線上例子

四、命名檢視(多個路由渲染出口)

使用場景

  1. 同時 (同級) 展示多個檢視
  2. 巢狀檢視的複雜佈局。(將巢狀元件視為根元件,則等同於場景1,不過是在routes內配置或children內配置的區別)

要點概括

  1. 配置多個路由渲染出口<router-view>並設定name屬性
  2. 路由配置時使用components欄位代替component欄位 多個s
  3. components物件內,key為<router-view>標籤的name屬性(沒設定時,預設為default),value為要渲染的元件
// App.vue
// 在模板中,配置多個路由渲染出口`<router-view>`並設定`name`屬性
<template>
  <div>
    <p>命名檢視</p>
    <p>
      <router-link to="/">主頁</router-link>
    </p>
    <router-view></router-view>
    <router-view name="view1"></router-view>
    <router-view name="view2"></router-view>
  </div>
</template>

// Main.js 
// 配置路由時使用components欄位代替component欄位,key為<router-view>標籤的`name`屬性(沒設定時,預設為`default`),value為要渲染的元件
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Index,
        view1: View1,
        view2: View2
      }
    }
  ]
})
複製程式碼

檢視線上例子

五、路由導航跳轉方法總結

mehtods: {
  routerMethodsCollection() {
    // router.push
    // 類似 window.history.pushState,會在history中產生新紀錄,回退按鈕可退回
    // 點選 <router-link> 內部呼叫router.push,故<router-link :to="..."> 對應 router.push(...)
    this.$router.push('/home') // 傳入路徑字串
    this.$router.push({ path: 'home' }) // 傳入路由描述物件
    // 路由傳參,如果指定了path則會傳參失敗
    this.$router.push({ name: 'user', params: { userId: 123 }}) // 傳入路由描述物件
    // 帶查詢引數,變成 /userlist?sex=male
    this.$router.push({ path: '/userlist', query: { sex: 'male' }})
    
    // router.replace
    // 類似 window.history.replaceState不會向 history 新增新記錄,而是替換掉當前記錄,其他與router.push無異
    // <router-link :to="..." replace> 對應	router.replace(...)
    this.$router.replace('/home') // 傳入路徑字串
    this.$router.replace({ path: 'home' }) // 傳入路由描述物件

    // router.go
    // 類似 window.history.go
    this.$router.go(1) // 前進一步,等同於 history.forward()
    this.$router.go(-1) // 後退一步,等同於 history.back()
    this.$router.go(-1) // 後退三步,等同於 history.go(-3)
  }
}
複製程式碼

檢視線上例子

六、路由傳參

動態路由匹配也算是一種路由傳參,詳見第二大點二、動態路由匹配(相當於路由傳參)

最常用的傳參方式就是通過以下兩種方式:

  1. <router-link> 標籤中的to屬性的路由物件傳入欄位params
  2. router.push中的路由物件傳入欄位params

上面兩種方式本質上是相同的,只不過是宣告式和程式設計式兩種表現

這裡需要注意的是,傳入的路由物件中,如果傳入了path欄位,則params欄位會被忽略。所以當需要傳參時,一般傳入name欄位來描述路由地址。

// Main.js 
// 配置路由時注意需傳參的路由要進行命名
const router = new VueRouter({
  routes : [
    {path: '/home',component: Home},
    {path: '/param',component: Param, name: 'param'}
  ]
})

// App.vue
// 在模板中,配置路由渲染出口及傳參
<template>
  <div>
    <p>路由傳參</p>
    <p>
      <router-link to="/">主頁</router-link>
      <router-link to="{name: 'param', params: {msg: '宣告式路由跳轉傳入的引數'}}">宣告式傳參</router-link>
      <button @click="$router.push({name: 'param', params: {msg: '程式設計式路由跳轉傳入的引數'}})">程式設計式傳參</button>
    </p>
    <router-view></router-view>
  </div>
</template>

// Param.vue 中接收引數
<template>
  <div>
    <p>接收的引數:{{$route.params.msg}}</p>
  </div>
</template>
複製程式碼

檢視線上例子

七、路由重定向和別名

// 路由重定向
// 意味著訪問/a會定向到/b,URL也會變為/b
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' },
    { path: '/c', redirect: {name: 'use'}}
  ]
})

// 路由別名
// 意味著訪問/b會匹配到/a,URL保持為/b
const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
    { path: '/a', component: A, alias: ['/b', '/c'] }
  ]
})
複製程式碼

檢視線上例子

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

  • 全域性前置守衛:beforeEach
  • 全域性解析守衛:beforeResolve
  • 全域性後置鉤子:afterEach
  • 路由守衛:beforeEnter
  • 元件守衛:beforeRouteEnter
  • 元件守衛:beforeRouteUpdate
  • 元件守衛:beforeRouteLeave
// Main.js中
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home,
      // 【路由守衛beforeEnter】
      beforeEnter(to, from, next) {
        console.log('路由守衛:beforeEnter')
        // ...
        next() // 確保要呼叫 next 方法
      }
    }
  ]
})

// 【全域性前置守衛beforeEach】
router.beforeEach((to, from, next) => {
  console.log('全域性前置守衛:beforeEach')
  // ...
  next() // 確保要呼叫 next 方法,否則鉤子就不會被 resolved
})

// 【全域性解析守衛beforeResolve】
router.beforeResolve((to, from, next) => {
  console.log('全域性解析守衛:beforeResolve')
  // ...
  next() // 確保要呼叫 next 方法,否則鉤子就不會被 resolved
})

// 【全域性後置鉤子afterEach】
router.afterEach((to, from) => {
  console.log('全域性後置鉤子:afterEach')
  // ...
})

// Home.vue中
export default {
  // 【元件守衛beforeRouteEnter】
  beforeRouteEnter (to, from, next) {
    // 在渲染該元件的對應路由被 confirm 前呼叫
    // 不!能!獲取元件例項 `this`,可以傳一個回撥給 next,將元件例項作為引數來訪問元件例項
    console.log('元件守衛:beforeRouteEnter')
    next(vm => {
      // vm即為元件例項
    })
  },

  // 【元件守衛beforeRouteUpdate】
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,但是該元件被複用時呼叫,例如動態路由
    // 可以訪問元件例項 `this`
    console.log('元件守衛:beforeRouteUpdate')
    next() // 確保要呼叫 next 方法
  },

  // 【元件守衛beforeRouteLeave】
  beforeRouteLeave (to, from, next) {
    // 導航離開該元件的對應路由時呼叫
    // 可以訪問元件例項 `this`
    console.log('元件守衛:beforeRouteLeave')
    next() // 確保要呼叫 next 方法
  },
  created() {
    console.log('元件生命週期:created')
  },
  mounted() {
    console.log('元件生命週期:mounted')
  }
}
複製程式碼

執行順序

檢視線上例子

參考文章

十全大補vue-router

vue-router詳解

這兩天學習vue-router的筆記,後續學習到的地方再做補充,有誤的地方求大神指出

相關文章