Vue路由(vue-router)詳細講解指南

  • 2019 年 10 月 3 日
  • 筆記

中文文檔:https://router.vuejs.org/zh/

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。路由實際上就是可以理解為指向,就是我在頁面上點擊一個按鈕需要跳轉到對應的頁面,這就是路由跳轉;

首先我們來學習三個單詞(route,routes,router):

  route:首先它是個單數,譯為路由,即我們可以理解為單個路由或者某一個路由;

  routes:它是個複數,表示多個的集合才能為複數;即我們可以理解為多個路由的集合,JS中表示多種不同狀態的集合的形式只有數組和對象兩種,事實上官方定義routes是一個數組;所以我們記住了,routes表示多個數組的集合;

  router:譯為路由器,上面都是路由,這個是路由器,我們可以理解為一個容器包含上述兩個或者說它是一個管理者,負責管理上述兩個;舉個常見的場景的例子:當用戶在頁面上點擊按鈕的時候,這個時候router就會去routes中去查找route,就是說路由器會去路由集合中找對應的路由;

 

我們結合一個小demo來看(文章有點長,耐心慢慢看,學得慢才能進步的快,當然可以跟著一起敲):

  首先需要安裝vue-cli來構建一個vue的開發環境(怎麼安裝這裡不講,自己百度去,如果這種問題自己都解決不了的話,後面的知識可能對你來說收益不大)

  安裝完vue-cli之後,我們的項目目錄結構如下:

   

 

 

   然後我們在命令行中輸入npm install vue-router -g來安裝vue-router,安裝完之後我們可以打開package.json文件,在package.json文件中可以看到vue-router的版本號;

 

 

 到這一步我們的準備工作就完成了,要進行寫demo了;

 

我們在src目錄下新建三個文件,分別為page1.vue和page2.vue以及router.js:

page1.vue:

 

<template>      <div>          <h1>page1</h1>          <p>{{msg}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  msg: "我是page1組件"              }          }      }  </script>

 

 page2.vue:

 

<template>      <div>          <h1>page2</h1>          <p>{{msg}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  msg: "我是page2組件"              }          }      }  </script>

 

router.js

//引入vue  import Vue from 'vue';  //引入vue-router  import VueRouter from 'vue-router';  //第三方庫需要use一下才能用  Vue.use(VueRouter)  //引用page1頁面  import page1  from './page1.vue';  //引用page2頁面  import page2  from './page2.vue';    //定義routes路由的集合,數組類型  const routes=[      //單個路由均為對象類型,path代表的是路徑,component代表組件      {path:'/page1',component:page1},      {path:"/page2",component:page2}  ]    //實例化VueRouter並將routes添加進去  const router=new VueRouter({  //ES6簡寫,等於routes:routes      routes  });    //拋出這個這個實例對象方便外部讀取以及訪問  export default router

這裡我們再修改一下main.js

import Vue from 'vue'  import App from './App'  //引用router.js  import router from './router.js'  Vue.config.productionTip = false    /* eslint-disable no-new */  new Vue({    el: '#app',  //一定要注入到vue的實例對象上    router,    components: { App },    template: '<App/>'  })

修改App.vue

  

<template>    <div id="app">      <img src="./assets/logo.png">      <div>  //router-link定義頁面中點擊觸發部分          <router-link to="/page1">Page1</router-link>        <router-link to="/page2">Page2</router-link>      </div>  //router-view定義頁面中顯示部分      <router-view></router-view>    </div>  </template>    <script>  export default {    name: 'App'  }  </script>    <style>  #app {    font-family: 'Avenir', Helvetica, Arial, sans-serif;    -webkit-font-smoothing: antialiased;    -moz-osx-font-smoothing: grayscale;    text-align: center;    color: #2c3e50;    margin-top: 60px;  }  </style>

 

就這樣,我們的頁面就可以進行路由跳轉和切換了,路由的基本使用就完成了;但是有個問題就是我們第一次進去是看不到路由頁面的,這是因為我們沒有設置默認值,我們首次進入的時候路徑是為空的,那麼我們可以這麼解決:

router.js

 

import Vue from 'vue';  import VueRouter from 'vue-router';  Vue.use(VueRouter)  import page1  from './page1.vue';  import page2  from './page2.vue';  import user   from './user.vue'    const routes=[      {path:'/page1',component:page1},      {path:"/page2",component:page2},      //可以配置重定向      {path:'',redirect:"page1"}      //或者重新寫個路徑為空的路由      {path:"",component:page1}  ]    const router=new VueRouter({      routes  });    export default router

 

上面的兩種解決方案都是可以解決的,配置重定向的意思就是當匹配到路徑為空的時候,就會重定向到page1,執行page1的路由;或者我們也可以重新配置個路由,路徑為空的時候router-view展示page1的頁面;

用重定向和單獨配置路由的區別:

  重定向實際上是當匹配到路徑符合條件的時候去執行對應的路由,當然這個時候的url上面的地址顯示的是對應的路由,頁面也是對應的路由頁面;

  重新配置路由是當匹配到路徑符合條件的時候,router-view頁面展示部分負責拿符合條件路由的頁面來展示,實際上url是沒有發生變化的;

 

那麼還有些複雜情況,是基本路由實現不了的;我們來接著往下看

 

動態路由匹配:

  其實我們的生活中有很多這樣的例子,不知道大家留意沒有?比如一個網站或者後台管理系統中,在我們登錄之後,是不是通常會有一個歡迎回來,XXX之類的提示語,這個我們就可以通過動態路由來實現這個效果;

 

首先在src目錄下新建一個user.vue文件:

<template>      <div>          <h1>user</h1>         //這裡可以通過$route.params.name來獲取路由的參數          <p>歡迎回來,{{$route.params.name}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  msg: "我是page1組件"              }          }      }  </script>

 

然後我們修改App.vue文件的程式碼:

<template>    <div id="app">      <img src="./assets/logo.png">      <div>        <router-link to="/page1">Page1</router-link>        <router-link to="/page2">Page2</router-link>      </div>    //添加兩個router-link標籤      <div>        <router-link to="/user/xianyu">動態路由鹹魚</router-link>        <router-link to="/user/mengxiang">動態路由夢想</router-link>      </div>      <router-view></router-view>    </div>  </template>    <script>  export default {    name: 'App'  }  </script>    <style>  #app {    font-family: 'Avenir', Helvetica, Arial, sans-serif;    -webkit-font-smoothing: antialiased;    -moz-osx-font-smoothing: grayscale;    text-align: center;    color: #2c3e50;    margin-top: 60px;  }  </style>

修改我們的router.js

import Vue from 'vue';  import VueRouter from 'vue-router';  Vue.use(VueRouter)  import page1  from './page1.vue';  import page2  from './page2.vue';  import user   from './user.vue'    const routes=[      {path:'/page1',component:page1},      {path:"/page2",component:page2},      // {path:'',redirect:"page1"}      {path:"",component:page1},   //使用冒號標記,當匹配到的時候,參數值會被設置到this.$route.params中      {path:"/user/:name",component:user}    ]    const router=new VueRouter({      routes  });    export default router

配置好了,不出意外是能正常運行的,我們來看一下效果:

 

 

 動態路由匹配給我們提供了方便,使得我們通過配置一個路由來實現頁面局部修改的效果,給用戶造成一種多個頁面的感覺,是不是很酷!!!

酷的同時也會給我們帶來一些問題,因為使用路由參數時,從/user/xianyu導航到/user/mengxiang,原來的組件實例會被複用,兩個路由都渲染同個組件,比起銷毀再創建,顯示復用顯得效率更高,帶來的的只管問題就是生命周期鉤子函數不會再被調用,也就是不會再被觸發;但是辦法總比問題多,我們可以通過監聽$route對象來實現;

修改user.vue的程式碼

<template>      <div>          <h1>user</h1>          <p>歡迎回來,{{msg}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  // msg: "我是page1組件"                  msg:""              }          },          watch:{  //to表示即將要進入的那個組件,from表示從哪個組件過來的              $route(to,from){                  this.msg=to.params.name;                  console.log(111);              }          }      }  </script>

效果圖如下:

 

 

 我們可以很明顯的看到我們監聽的$route對象被觸發了,控制台也輸出了;

下面我們來一起看一下嵌套路由:

 

  嵌套路由:

    很多時候我們的頁面結構決定了我們可能需要嵌套路由,比如當我們進入主頁之後有分類,然後當選擇其中一個分類之後進入對應的詳情,這個時候我們就可以用到嵌套路由;官方文檔中給我們提供了一個children屬性,這個屬性是一個數組類型,裡面實際放著一組路由;這個時候父子關係結構就出來了,所以children屬性裡面的是路由相對來說是children屬性外部路由的子路由;

好記性不如爛程式碼,讓我們通過程式碼來看一看:

  首先在我們的src目錄下新建兩個vue文件,分別是phone.vue和computer.vue

  phone.vue

<template>      <div>          <p>{{msg}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  msg: "嵌套手機組件"              }          }      }  </script>

  computer.vue

<template>      <div>          <p>{{msg}}</p>      </div>  </template>  <script>      export default {          data () {              return {                  msg: "嵌套電腦組件"              }          }      }  </script>

然後我們再修改我們的App.vue文件:

<template>    <div id="app">      <img src="./assets/logo.png">      <div>        <router-link to="/page1">Page1</router-link>      </div>      <router-view></router-view>    </div>  </template>    <script>  export default {    name: 'App'  }  </script>    <style>  #app {    font-family: 'Avenir', Helvetica, Arial, sans-serif;    -webkit-font-smoothing: antialiased;    -moz-osx-font-smoothing: grayscale;    text-align: center;    color: #2c3e50;    margin-top: 60px;  }  </style>

通過上面的App.vue文件我們可以看到,我們此時頁面只有一個page1的標籤了;

我們再來修改router.js

import Vue from 'vue';  import VueRouter from 'vue-router';  Vue.use(VueRouter)  import page1  from './page1.vue';  import page2  from './page2.vue';  import user   from './user.vue';  import phone  from './phone.vue';  import computer from './computer.vue'    const routes=[      {          path:'/page1',          component:page1,          children: [              {                  path: "phone",                  component: phone              },              {                  path: "computer",                  component: computer              },          ]      },      // {path:"/page2",component:page2},      // // {path:'',redirect:"page1"}      // {path:"",component:page1},      // {path:"/user/:name",component:user}    ]    const router=new VueRouter({      routes  });    export default router

為了大家看的直觀點,其他路由全部注釋了,頁面只剩下/page1這一個路由了;

 

 

 

上面說到了,children屬性其實就是一個子路由集合,數組結構裡面放著子路由;

效果圖如下:

 

 

 路由導航兩種方式:

  標籤導航:標籤導航<router-link><router-link>是通過轉義為<a></a>標籤進行跳轉,其中router-link標籤中的to屬性會被轉義為a標籤中的href屬性;

 

//跳轉到名為user路由,並傳遞參數userId  <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

 

 

 

  編程式導航:我們可以通過this.$router.push()這個方法來實現編程式導航,當然也可以實現參數傳遞,這種編程式導航一般是用於按鈕點擊之後跳轉

router.push({ name: 'user', params: { userId: 123 }})

這兩者都會把路由導航到user/123路徑

命名路由:

  有的時候,通過一個名稱來標識一個路由顯得更方便一些,所以官方為了方便我們偷懶,又給我們在路由中添加了一個name屬性,命名這個屬性之後我們訪問這個屬性就等於直接訪問到路由;

  普通路由:

router.push({ path: '/user/:userId', params: { userId: 123 }})

 

  命名路由:

router.push({ name: 'user', params: { userId: 123 }})

其實兩者並沒有什麼區別,只是提供了兩種方式來訪問路由,可以通過路徑來匹配也可以通過別名來匹配;

 

 

 

 今天的文章就到這裡,下篇我們一起來學習Vue路由守衛!!!

加油!!