路由,其實就是指向的意思,當我點擊頁面上的home按鈕時,頁面中就要顯示home的內容,若是點擊頁面上的about 按鈕,頁面中就要顯示about 的內容。Home按鈕 => home 內容, about按鈕 => about 內容,也能夠說是一種映射. 因此在頁面上有兩個部分,一個是點擊部分,一個是點擊以後,顯示內容的部分。 javascript
點擊以後,怎麼作到正確的對應,好比,我點擊home 按鈕,頁面中怎麼就正好能顯示home的內容。這就要在js 文件中配置路由。html
路由中有三個基本的概念 route, routes, router。vue
1, route,它是一條路由,由這個英文單詞也能夠看出來,它是單數, Home按鈕 => home內容, 這是一條route, about按鈕 => about 內容, 這是另外一條路由。html5
2, routes 是一組路由,把上面的每一條路由組合起來,造成一個數組。[{home 按鈕 =>home內容 }, { about按鈕 => about 內容}]java
3, router 是一個機制,至關於一個管理者,它來管理路由。由於routes 只是定義了一組路由,它放在哪裏是靜止的,當真正來了請求,怎麼辦? 就是當用戶點擊home 按鈕的時候,怎麼辦?這時router 就起做用了,它到routes 中去查找,去找到對應的 home 內容,因此頁面中就顯示了 home 內容。vue-router
4,客戶端中的路由,實際上就是dom 元素的顯示和隱藏。當頁面中顯示home 內容的時候,about 中的內容所有隱藏,反之也是同樣。客戶端路由有兩種實現方式:基於hash 和基於html5 history api.vuex
vue-router中的路由也是基於上面的內容來實現的vue-cli
在vue中實現路由仍是相對簡單的。由於咱們頁面中全部內容都是組件化的,咱們只要把路徑和組件對應起來就能夠了,而後在頁面中把組件渲染出來。編程
1, 頁面實現(html模版中)api
在vue-router中, 咱們看到它定義了兩個標籤<router-link> 和<router-view>來對應點擊和顯示部分。<router-link> 就是定義頁面中點擊的部分,<router-view> 定義顯示部分,就是點擊後,區配的內容顯示在什麼地方。因此 <router-link> 還有一個很是重要的屬性 to,定義點擊以後,要到哪裏去, 如:<router-link to="/home">Home</router-link>
2, js 中配置路由
首先要定義route, 一條路由的實現。它是一個對象,由兩個部分組成: path和component. path 指路徑,component 指的是組件。如:{path:’/home’, component: home}
咱們這裏有兩條路由,組成一個routes:
const routes = [ { path: '/home', component: Home }, { path: '/about', component: About } ]
最後建立router 對路由進行管理,它是由構造函數 new vueRouter() 建立,接受routes 參數。
const router = new VueRouter({ routes // routes: routes 的簡寫 })
配置完成後,把router 實例注入到 vue 根實例中,就可使用路由了
const app = new Vue({ router }).$mount('#app')
執行過程:當用戶點擊 router-link 標籤時,會去尋找它的 to 屬性, 它的 to 屬性和 js 中配置的路徑{ path: '/home', component: Home} path 一一對應,從而找到了匹配的組件, 最後把組件渲染到 <router-view> 標籤所在的地方。全部的這些實現纔是基於hash 實現的。
vue-cli 建立一個項目體驗一下, 固然不要忘記安裝vue-router
1, 在src 目錄下新建兩個組件,home.vue 和 about.vue
複製代碼 <template> <div> <h1>home</h1> <p>{{msg}}</p> </div> </template> <script> export default { data () { return { msg: "我是home 組件" } } } </script>
<template> <div> <h1>about</h1> <p>{{aboutMsg}}</p> </div> </template> <script> export default { data () { return { aboutMsg: '我是about組件' } } } </script>
2, 在 App.vue中 定義<router-link > 和 </router-view>
<template> <div id="app"> <img src="./assets/logo.png"> <header> <!-- router-link 定義點擊後導航到哪一個路徑下 --> <router-link to="/home">Home</router-link> <router-link to="/about">About</router-link> </header> <!-- 對應的組件內容渲染到router-view中 --> <router-view></router-view> </div> </template> <script> export default { } </script>
3, 在 src目錄下再新建一個router.js 定義router, 就是定義 路徑到 組件的 映射。
import Vue from "vue"; import VueRouter from "vue-router"; // 引入組件 import home from "./home.vue"; import about from "./about.vue"; // 要告訴 vue 使用 vueRouter Vue.use(VueRouter); const routes = [ { path:"/home", component: home }, { path: "/about", component: about } ] var router = new VueRouter({ routes }) export default router;
4, 把路由注入到根實例中,啓動路由。這裏其實還有一種方法,就像vuex store 注入到根實例中同樣,咱們也能夠把vueRouter 直接注入到根實例中。在main.js中引入路由,注入到根實例中。
import Vue from 'vue' import App from './App.vue' // 引入路由 import router from "./router.js" // import router 的router 必定要小寫, 不要寫成Router, 不然報 can't match的報錯 new Vue({ el: '#app', router, // 注入到根實例中 render: h => h(App) })
5, 這時點擊頁面上的home 和about 能夠看到組件來回切換。可是有一個問題,當首次進入頁面的時候,頁面中並無顯示任何內容。這是由於首次進入頁面時,它的路徑是 '/',咱們並無給這個路徑作相應的配置。通常,頁面一加載進來都會顯示home頁面,咱們也要把這個路徑指向home組件。可是若是咱們寫{ path: '/', component: Home },vue 會報錯,由於兩條路徑卻指向同一個方向。這怎麼辦?這須要重定向,所謂重定向,就是從新給它指定一個方向,它原本是訪問 / 路徑,咱們從新指向‘/home’, 它就至關於訪問 '/home', 相應地, home組件就會顯示到頁面上。vueRouter中用 redirect 來定義重定向。
const routes = [ { path:"/home", component: home }, { path: "/about", component: about }, // 重定向 { path: '/', redirect: '/home' } ]
如今頁面正常了,首次進入顯示home, 而且點擊也能夠看到內容的切換。
6, 最後,咱們看一下路由是怎麼實現的
打開瀏覽器控制檯,首先看到 router-link 標籤渲染成了 a 標籤,to 屬性變成了a 標籤的 href 屬性,這時就明白了點擊跳轉的意思。router-view 標籤渲染成了咱們定義的組件,其實它就是一個佔位符,它在什麼地方,匹配路徑的組件就在什麼地方,因此 router-link 和router-view 標籤一一對應,成對出現。
這裏還看到,當點擊Home和About 來回切換時,a 標籤有一個樣式類 .router-link-active 也在來回切換, 原來這是當router-link 處於選中狀態時,vueRouter 會自動添加這個類,所以咱們也能夠利用這個類來改變選中時的狀態,如選中時,讓它變成紅色。但當設置 .router-link-active {color: red;},它並無生效,這時還要在類前面加一個a, a.router-link-active {color: red;}, 這樣就沒有問題了。未處於選中狀態的router-link, 咱們也想給它更改樣式,怎麼辦? 直接給它添加一個 class 就能夠了, <router-link class="red">Home</router-link>
動態路由
上面咱們定義的路由,都是嚴格匹配的,只有router-link 中的to屬性和 js 中一條路由route中 path 如出一轍,才能顯示相應的組件component. 但有時現實卻不是這樣的,當咱們去訪問網站並登陸成功後,它會顯示 歡迎你,+ 你的名字。不一樣的用戶登陸, 只是顯示「你的名字」 部分不一樣,其它部分是同樣的。這就表示,它是一個組件,假設是user組件。不一樣的用戶(就是用戶的id不一樣),它都會導航到同一個user 組件中。這樣咱們在配置路由的時候,就不能寫死, 就是路由中的path屬性,不能寫死,那要怎麼設置? 導航到 user 組件,路徑中確定有user, id 不一樣,那就給路徑一個動態部分來匹配不一樣的id. 在vue-router中,動態部分 以 : 開頭,那麼路徑就變成了 /user/:id, 這條路由就能夠這麼寫: { path:"/user/:id", component: user }.
咱們定義一個user組件(本身隨便寫一個就行了),頁面中再添加兩個router-link 用於導航, 最後router.js中添加路由配置,來體驗一下
app.vue 中添加兩個router-link:
複製代碼 <template> <div id="app"> <img src="./assets/logo.png"> <header> <router-link to="/home">Home</router-link> <router-link to="/about">About</router-link> <!-- 增長兩個到user組件的導航,能夠看到這裏使用了不一樣的to屬性 --> <router-link to="/user/123">User123</router-link> <router-link to="/user/456">User456</router-link> </header> <router-view></router-view> </div> </template>
router.js 配置user動態路由:
const routes = [ { path:"/home", component: home }, { path: "/about", component: about }, /*新增user路徑,配置了動態的id*/ { path: "/user/:id", component: user }, { path: '/', redirect: '/home' } ]
user組件
<template> <div> <h1>User</h1> <div>我是user組件</div> </div> </template> <script> export default { } </script>
這時在頁面中點擊user123 和user456, 能夠看到它們都導航到user組件,配置正確。
在動態路由中,怎麼獲取到動態部分? 由於在組件中是能夠顯示不一樣部分的,就是上面提到的「你的名字」。其實,當整個vue-router 注入到根實例後,在組件的內部,能夠經過this.$route 來獲取到 router 實例。它有一個params 屬性,就是來得到這個動態部分的。它是一個對象,屬性名,就是路徑中定義的動態部分 id, 屬性值就是router-link中to 屬性中的動態部分,如123。使用vuex時,組件中想要獲取到state 中的狀態,是用computed 屬性,在這裏也是同樣,在組件中,定義一個computed 屬性dynamicSegment, user 組件修改以下:
<template> <div> <h1>User</h1> <div>我是user組件, 動態部分是{{dynamicSegment}}</div> </div> </template> <script> export default { computed: { dynamicSegment () { return this.$route.params.id } } } </script>
這裏還有最後一個問題,就是動態路由在來回切換時,因爲它們都是指向同一組件,vue不會銷燬再建立這個組件,而是複用這個組件,就是當第一次點擊(如:user123)的時候,vue 把對應的組件渲染出來,但在user123, user456點擊來回切換的時候,這個組件就不會發生變化了,組件的生命週期無論用了。這時若是想要在組件來回切換的時候作點事情,那麼只能在組件內部(user.vue中)利用watch 來監聽$route 的變化。把上面的代碼用監聽$route 實現
<script> export default { data () { return { dynamicSegment: '' } }, watch: { $route (to,from){ // to表示的是你要去的那個組件,from 表示的是你從哪一個組件過來的,它們是兩個對象,你能夠把它打印出來,它們也有一個param 屬性 console.log(to); console.log(from); this.dynamicSegment = to.params.id } } } </script>
嵌套路由
嵌套路由,主要是由咱們的頁面結構所決定的。當咱們進入到home頁面的時候,它下面還有分類,如手機系列,平板系列,電腦系列。當咱們點擊各個分類的時候,它仍是須要路由到各個部分,如點擊手機,它確定到對應到手機的部分。
在路由的設計上,首先進入到 home ,而後才能進入到phone, tablet, computer. Phone, tablet, compute 就至關於進入到了home的子元素。因此vue 提供了childrens 屬性,它也是一組路由,至關於咱們所寫的routes。
首先,在home頁面上定義三個router-link 標籤用於導航,而後再定義一個router-view標籤,用於渲染對應的組件。router-link 和router-view 標籤要一一對應。home.vue 組件修改以下:
<template> <div> <h1>home</h1> <!-- router-link 的to屬性要注意,路由是先進入到home,而後才進入相應的子路由如 phone,因此書寫時要把 home 帶上 --> <p> <router-link to="/home/phone">手機</router-link> <router-link to="/home/tablet">平板</router-link> <router-link to="/home/computer">電腦</router-link> </p> <router-view></router-view> </div> </template>
router.js 配置路由,修改以下:
const routes = [ { path:"/home", // 下面這個屬性也很多,由於,咱們是先進入home頁面,才能進入子路由 component: home, // 子路由 children: [ { path: "phone", component: phone }, { path: "tablet", component: tablet }, { path: "computer", component: computer } ] }, { path: "/about", component: about }, { path: "/user/:id", component: user }, { path: '/', redirect: '/home' } ]
這時當咱們點擊home 時,它下面出現手機等字樣,但沒有任何對應的組件進行顯示,這一般不是咱們想要的。要想點擊home時,要想渲染相對應的子組件,那還須要配置一條路由。當進入到home 時,它在children中對應的路由path 是空 ‘’,完整的childrens 以下:
children: [ { path: "phone", component: phone }, { path: "tablet", component: tablet }, { path: "computer", component: computer }, // 當進入到home時,下面的組件顯示 { path: "", component: phone } ]
命名路由
命名路由,很簡單,由於根據名字就能夠知道,這個路由有一個名字,那就直接給這個路由加一個name 屬性,就能夠了。 給user 路由加一個name 屬性:
{ path: "/user/:id", name: "user", component: user }
命名路由的使用, 在router-link 中to 屬性就可使用對象了,
<router-link to="/user/123">User123</router-link> // 和下面等價 <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> // 當使用對象做爲路由的時候,to前面要加一個冒號,表示綁定
編程式導航:這主要應用到按鈕點擊上。當點擊按鈕的時候,跳轉另外一個組件, 這隻能用代碼,調用rourter.push() 方法。 當們把router 注入到根實例中後,組件中經過 this.$router 能夠獲取到router, 因此在組件中使用
this.$router.push("home"), 就能夠跳轉到home界面