Vue Router 學(xué)習

我們在構(gòu)建復(fù)雜系統(tǒng)的時候,需要構(gòu)建多頁面來完成不同的功能,在使用多個頁面的時候,用層級路徑來標示頁面。vue router 將組件掛載在路由上的方式來模擬傳統(tǒng)的多頁應(yīng)用的效果,從而構(gòu)建復(fù)雜的單頁應(yīng)用。所以路由主要完成的是根據(jù)當前的路徑完成頁面的切換。

如何使用

注冊路由

首先構(gòu)建路由和組件之間的對應(yīng)關(guān)系

// 0. 如果使用模塊化機制編程,導(dǎo)入Vue和VueRouter,要調(diào)用 Vue.use(VueRouter)

// 1. 定義 (路由) 組件。
// 可以從其他文件 import 進來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定義路由
// 每個路由應(yīng)該映射一個組件。 其中"component" 可以是
// 通過 Vue.extend() 創(chuàng)建的組件構(gòu)造器,
// 或者,只是一個組件配置對象。
// 我們晚點再討論嵌套路由。
const routes = [
  {path: "/foo", component: Foo},
  {path: "/bar", component: Bar},
  //命名路由的方式
  {
    path: '/user/:userId',
    name: 'user',
    component: User
  }
]
// 3. 創(chuàng)建 router 實例,然后傳 `routes` 配置
// 你還可以傳別的配置參數(shù), 不過先這么簡單著吧。
const router = new VueRouter({
  routes
})

// 4. 創(chuàng)建和掛載根實例。
// 記得要通過 router 配置參數(shù)注入路由,
// 從而讓整個應(yīng)用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

路由導(dǎo)航和顯示對應(yīng)的內(nèi)容

利用<router-link>模擬<a>,進行頁面之間的導(dǎo)航。利用<router-view>來控制當前路由的對應(yīng)的控件顯示的區(qū)域。

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 組件來導(dǎo)航. -->
    <!-- 通過傳入 `to` 屬性指定鏈接. -->
    <!-- <router-link> 默認會被渲染成一個 `<a>` 標簽 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
    <!-- 命名的路由方式 -->
    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的組件將渲染在這里 -->
  <router-view></router-view>
</div>

路由的代碼操作

this.$route 用于訪問當前的路由,比如this.$route.params.username用于訪問動態(tài)路由里面的參數(shù)

router.push

router.push(location, onComplete?, onAbort?)

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

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

// 命名的路由,給定路由名稱的情況下,用這種方式導(dǎo)航
router.push({ name: 'user', params: { userId: '123' }})

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

注意:如果提供了 path,params 會被忽略,上述例子中的 query 并不屬于這種情況。取而代之的是下面例子的做法,你需要提供路由的 name 或手寫完整的帶有參數(shù)的 path

router.replace

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

router.go(n)

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

// 在瀏覽器記錄中前進一步,等同于 history.forward()
router.go(1)

// 后退一步記錄,等同于 history.back()
router.go(-1)

// 前進 3 步記錄
router.go(3)

// 如果 history 記錄不夠用,那就默默地失敗唄
router.go(-100)
router.go(100)

路由的種類

路由匹配順序

由于動態(tài)路由匹配存在,一個路徑可能匹配多個路由規(guī)則,路由匹配順序按照路由定義的優(yōu)先級來,誰先定義,誰的優(yōu)先級就高。

動態(tài)路由匹配

主要用于將屬于同一類的不同路由映射到同一個組件里面,路由的不同部分會被參數(shù)化匹配,如

  routes: [
    // 動態(tài)路徑參數(shù) 以冒號開頭
    { path: '/user/:id', component: User }
  ]
匹配的方式
動態(tài)路徑參數(shù)

一個“路徑參數(shù)”使用冒號 : 標記。當匹配到一個路由時,參數(shù)值會被設(shè)置到 this.$route.params,可以在每個組件內(nèi)使用。于是,我們可以更新 User 的模板,輸出當前用戶的 ID。
在不同的路由之間進行導(dǎo)航的時候,如果對應(yīng)的是同一個組件,那么組件會被復(fù)用,也就是意味著組件的生命周期鉤子不會再被調(diào)用。所以想要檢測路由的變化和頁面的重新刷新,可以了用檢測路由變化,或者利用導(dǎo)航守衛(wèi)。

  watch: {
    '$route' (to, from) {
      // 對路由變化作出響應(yīng)...
    }
  }
const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}
匹配所有路由

主要用以客戶端 404 錯誤,為剩余的路由設(shè)置一個默認顯示。所以一般放在最后。

{
  // 會匹配所有路徑
  path: '*'
}
{
  // 會匹配以 `/user-` 開頭的任意路徑
  path: '/user-*'
}

當使用一個通配符時,$route.params 內(nèi)會自動添加一個名為 pathMatch 參數(shù)。它包含了 URL 通過通配符被匹配的部分:

// 給出一個路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 給出一個路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
高級匹配模式

支持以正則表達式的方式來匹配路由,依賴path-to-regexp來實現(xiàn)。

嵌套路由

實際生活中的應(yīng)用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態(tài)路徑也按某種結(jié)構(gòu)對應(yīng)嵌套的各層組件,例如:

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

借助 vue-router,使用嵌套路由配置,就可以很簡單地表達這種關(guān)系。也就是說被路由渲染的組件里面還有包含路由渲染路由<router-view>。這通過子路由的方式來實現(xiàn)

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        // 當 /user/:id 匹配成功,
        // UserHome 會被渲染在 User 的 <router-view> 中
        { path: '', component: UserHome },

        // ...其他子路由
        {
          // 當 /user/:id/profile 匹配成功,
          // UserProfile 會被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 當 /user/:id/posts 匹配成功
          // UserPosts 會被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

顯示多個路由視圖-命名視圖

有時候想同時 (同級) 展示多個視圖,而不是嵌套展示,例如創(chuàng)建一個布局,有 sidebar (側(cè)導(dǎo)航) 和 main (主內(nèi)容) 兩個視圖,這個時候命名視圖就派上用場了。你可以在界面中擁有多個單獨命名的視圖,而不是只有一個單獨的出口。如果 router-view 沒有設(shè)置名字,那么默認為 default。

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

構(gòu)建路由的方式也有變化,變成了多組件

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

嵌套路由和命名路由組合

我們也有可能使用命名視圖創(chuàng)建嵌套視圖的復(fù)雜布局。這時你也需要命名用到的嵌套 router-view 組件。我們以一個設(shè)置面板為例:

/settings/emails                                       /settings/profile
+-----------------------------------+                  +------------------------------+
| UserSettings                      |                  | UserSettings                 |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | |  +------------>  | | Nav | UserProfile        | |
| |     +-------------------------+ |                  | |     +--------------------+ |
| |     |                         | |                  | |     | UserProfilePreview | |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
+-----------------------------------+                  +------------------------------+

UserSettings 組件的 <template> 部分應(yīng)該是類似下面的這段代碼:

<!-- UserSettings.vue -->
<div>
  <h1>User Settings</h1>
  <NavBar/>
  <router-view/>
  <router-view name="helper"/>
</div>

然后你可以用這個路由配置完成該布局:

{
  path: '/settings',
  // 你也可以在頂級路由就配置命名視圖
  component: UserSettings,
  children: [{
    path: 'emails',
    component: UserEmailsSubscriptions
  }, {
    path: 'profile',
    components: {
      default: UserProfile,
      helper: UserProfilePreview
    }
  }]
}

路由重定向

//重定向到路徑
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})
//重定向到命名路由
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})
//重定向到一個動態(tài)目標
const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目標路由 作為參數(shù)
      // return 重定向的 字符串路徑/路徑對象
    }}
  ]
})

重定向發(fā)生在進入路由之前,所以路由守衛(wèi)并不會被執(zhí)行。

路由別名

/a 的別名是 /b,意味著,當用戶訪問 /b 時,URL 會保持為 /b,但是路由匹配則為 /a,就像用戶訪問 /a 一樣。

上面對應(yīng)的路由配置為

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

給路由組件傳參

通過訪問路由參數(shù)可以獲取當前動態(tài)路由的參數(shù),但是這樣組件跟路由就耦合了,
通過使用 props 將組件和路由解耦:

const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: true },

    // 對于包含命名視圖的路由,你必須分別為每個命名視圖添加 `props` 選項:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

//靜態(tài)傳參
const router = new VueRouter({
  routes: [
    { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
  ]
})

//函數(shù)傳參
//URL /search?q=vue 會將 {query: 'vue'} 作為屬性傳遞給 SearchUser 組件。
const router = new VueRouter({
  routes: [
    { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
  ]
})

路由模式
vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當 URL 改變時,頁面不會重新加載。

如果不想要很丑的 hash,我們可以用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉(zhuǎn)而無須重新加載頁面。

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!

不過這種模式要玩好,還需要后臺配置支持。因為我們的應(yīng)用是個單頁客戶端應(yīng)用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。

所以呢,你要在服務(wù)端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應(yīng)該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

導(dǎo)航守衛(wèi)的調(diào)用順序

  1. 導(dǎo)航被觸發(fā)。
  2. 在失活的組件里調(diào)用離開守衛(wèi)。
  3. 調(diào)用全局的 beforeEach 守衛(wèi)。
  4. 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi) (2.2+)。
  5. 在路由配置里調(diào)用 beforeEnter。
  6. 解析異步路由組件。
  7. 在被激活的組件里調(diào)用 beforeRouteEnter。
  8. 調(diào)用全局的 beforeResolve 守衛(wèi) (2.5+)。
  9. 導(dǎo)航被確認。
  10. 調(diào)用全局的 afterEach 鉤子。
  11. 觸發(fā) DOM 更新。
  12. 用創(chuàng)建好的實例調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 學(xué)習目的 學(xué)習Vue的必備技能,必須 熟練使用 Vue-router,能夠在實際項目中運用。 Vue-rout...
    _1633_閱讀 92,883評論 3 58
  • vue-router學(xué)習筆記 安裝 并且如果在一個模塊化工程中使用它,必須要通過Vue.use()明確地安裝路由功...
    EL_PSY_CONGROO閱讀 674評論 0 0
  • 前言 vue-router是什么:是vue.js官方的路由管理器和vue.js的核心深度的集成,讓開發(fā)者更加簡單的...
    GUAN_one閱讀 3,858評論 0 2
  • 動態(tài)路由參數(shù),以冒號開頭配置,瀏覽器中的路徑不需要加冒號,類似于正則表達式對一個簡單字符串的匹配 匹配的優(yōu)先級就按...
    老邵閱讀 508評論 0 0
  • 一、前端路由 路由是根據(jù)不同的url地址顯示不同的內(nèi)容或頁面前端路由就是把不同路由對應(yīng)不同的內(nèi)容或頁面的任務(wù)交給前...
    puxiaotaoc閱讀 627評論 0 1

友情鏈接更多精彩內(nèi)容