[轉(zhuǎn)載自](http://www.cnblogs.com/SamWeb/p/6610733.html)
路由沪饺,其實就是指向的意思,當(dāng)我點擊頁面上的home按鈕時侍瑟,頁面中就要顯示home的內(nèi)容,如果點擊頁面上的about 按鈕,頁面中就要顯示about 的內(nèi)容能曾。Home按鈕 => home 內(nèi)容度硝, about按鈕 => about 內(nèi)容,也可以說是一種映射. 所以在頁面上有兩個部分寿冕,一個是點擊部分蕊程,一個是點擊之后,顯示內(nèi)容的部分驼唱。
點擊之后藻茂,怎么做到正確的對應(yīng),比如玫恳,我點擊home 按鈕辨赐,頁面中怎么就正好能顯示home的內(nèi)容。這就要在js 文件中配置路由京办。
路由中有三個基本的概念 route, routes, router掀序。
1, route惭婿,它是一條路由不恭,由這個英文單詞也可以看出來,它是單數(shù)财饥, Home按鈕 => home內(nèi)容换吧, 這是一條route, about按鈕 => about 內(nèi)容, 這是另一條路由佑力。
2式散, routes 是一組路由,把上面的每一條路由組合起來打颤,形成一個數(shù)組暴拄。[{home 按鈕 =>home內(nèi)容 }, { about按鈕 => about 內(nèi)容}]
3编饺, router 是一個機(jī)制乖篷,相當(dāng)于一個管理者,它來管理路由透且。因為routes 只是定義了一組路由撕蔼,它放在哪里是靜止的,當(dāng)真正來了請求秽誊,怎么辦鲸沮? 就是當(dāng)用戶點擊home 按鈕的時候,怎么辦锅论?這時router 就起作用了讼溺,它到routes 中去查找,去找到對應(yīng)的 home 內(nèi)容最易,所以頁面中就顯示了 home 內(nèi)容怒坯。
4炫狱,客戶端中的路由,實際上就是dom 元素的顯示和隱藏剔猿。當(dāng)頁面中顯示home 內(nèi)容的時候视译,about 中的內(nèi)容全部隱藏,反之也是一樣归敬】岷客戶端路由有兩種實現(xiàn)方式:基于hash 和基于html5 history api.
vue-router中的路由也是基于上面的內(nèi)容來實現(xiàn)的
在vue中實現(xiàn)路由還是相對簡單的。因為我們頁面中所有內(nèi)容都是組件化的弄慰,我們只要把路徑和組件對應(yīng)起來就可以了第美,然后在頁面中把組件渲染出來蝶锋。
1陆爽, 頁面實現(xiàn)(html模版中)
在vue-router中, 我們看到它定義了兩個標(biāo)簽 和來對應(yīng)點擊和顯示部分。 就是定義頁面中點擊的部分扳缕, 定義顯示部分慌闭,就是點擊后,區(qū)配的內(nèi)容顯示在什么地方躯舔。所以 還有一個非常重要的屬性 to驴剔,定義點擊之后,要到哪里去粥庄, 如:Home
2丧失, js 中配置路由
首先要定義route, 一條路由的實現(xiàn)。它是一個對象惜互,由兩個部分組成: path和component. path 指路徑布讹,component 指的是組件。如:{path:’/home’, component: home}
我們這里有兩條路由训堆,組成一個routes:
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
最后創(chuàng)建router 對路由進(jìn)行管理描验,它是由構(gòu)造函數(shù) new vueRouter() 創(chuàng)建,接受routes 參數(shù)坑鱼。
const router = new VueRouter({ routes // routes: routes 的簡寫})
配置完成后膘流,把router 實例注入到 vue 根實例中,就可以使用路由了
const app = new Vue({ router}).$mount('#app')
執(zhí)行過程:當(dāng)用戶點擊 router-link 標(biāo)簽時,會去尋找它的 to 屬性鲁沥, 它的 to 屬性和 js 中配置的路徑{ path: '/home', component: Home} path 一一對應(yīng)呼股,從而找到了匹配的組件, 最后把組件渲染到 <router-view> 標(biāo)簽所在的地方画恰。所有的這些實現(xiàn)才是基于hash 實現(xiàn)的彭谁。
vue-cli 創(chuàng)建一個項目體驗一下, 當(dāng)然不要忘記安裝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 定義點擊后導(dǎo)航到哪個路徑下 -->
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</header>
<!-- 對應(yīng)的組件內(nèi)容渲染到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 可以看到組件來回切換馆匿。但是有一個問題,當(dāng)首次進(jìn)入頁面的時候燥滑,頁面中并沒有顯示任何內(nèi)容渐北。這是因為首次進(jìn)入頁面時,它的路徑是 '/'铭拧,我們并沒有給這個路徑做相應(yīng)的配置赃蛛。一般,頁面一加載進(jìn)來都會顯示home頁面搀菩,我們也要把這個路徑指向home組件呕臂。但是如果我們寫{ path: '/', component: Home },vue 會報錯,因為兩條路徑卻指向同一個方向肪跋。這怎么辦歧蒋?這需要重定向,所謂重定向州既,就是重新給它指定一個方向谜洽,它本來是訪問 / 路徑,我們重新指向‘/home’, 它就相當(dāng)于訪問 '/home', 相應(yīng)地, home組件就會顯示到頁面上易桃。vueRouter中用 redirect 來定義重定向褥琐。
const routes = [
{
path:"/home",
component: home
},
{
path: "/about",
component: about
},
// 重定向
{
path: '/',
redirect: '/home'
}
]
現(xiàn)在頁面正常了,首次進(jìn)入顯示home, 并且點擊也可以看到內(nèi)容的切換晤郑。
6敌呈, 最后,我們看一下路由是怎么實現(xiàn)的
打開瀏覽器控制臺造寝,首先看到 router-link 標(biāo)簽渲染成了 a 標(biāo)簽磕洪,to 屬性變成了a 標(biāo)簽的 href 屬性,這時就明白了點擊跳轉(zhuǎn)的意思诫龙。router-view 標(biāo)簽渲染成了我們定義的組件析显,其實它就是一個占位符,它在什么地方签赃,匹配路徑的組件就在什么地方谷异,所以 router-link 和router-view 標(biāo)簽一一對應(yīng)分尸,成對出現(xiàn)。
這里還看到歹嘹,當(dāng)點擊Home和About 來回切換時箩绍,a 標(biāo)簽有一個樣式類 .router-link-active 也在來回切換, 原來這是當(dāng)router-link 處于選中狀態(tài)時尺上,vueRouter 會自動添加這個類材蛛,因此我們也可以利用這個類來改變選中時的狀態(tài),如選中時怎抛,讓它變成紅色卑吭。但當(dāng)設(shè)置 .router-link-active {color: red;},它并沒有生效马绝,這時還要在類前面加一個a, a.router-link-active {color: red;}, 這樣就沒有問題了豆赏。未處于選中狀態(tài)的router-link, 我們也想給它更改樣式迹淌,怎么辦? 直接給它添加一個 class 就可以了河绽, <router-link class="red">Home</router-link>
動態(tài)路由
上面我們定義的路由,都是嚴(yán)格匹配的唉窃,只有router-link 中的to屬性和 js 中一條路由route中 path 一模一樣,才能顯示相應(yīng)的組件component. 但有時現(xiàn)實卻不是這樣的纹笼,當(dāng)我們?nèi)ピL問網(wǎng)站并登錄成功后纹份,它會顯示 歡迎你,+ 你的名字廷痘。不同的用戶登錄蔓涧, 只是顯示“你的名字” 部分不同,其它部分是一樣的笋额。這就表示元暴,它是一個組件,假設(shè)是user組件兄猩。不同的用戶(就是用戶的id不同)茉盏,它都會導(dǎo)航到同一個user 組件中。這樣我們在配置路由的時候枢冤,就不能寫死, 就是路由中的path屬性鸠姨,不能寫死,那要怎么設(shè)置? 導(dǎo)航到 user 組件淹真,路徑中肯定有user, id 不同讶迁,那就給路徑一個動態(tài)部分來匹配不同的id. 在vue-router中,動態(tài)部分 以 : 開頭核蘸,那么路徑就變成了 /user/:id, 這條路由就可以這么寫: { path:"/user/:id", component: user }.
我們定義一個user組件(自己隨便寫一個就好了)巍糯,頁面中再添加兩個router-link 用于導(dǎo)航啸驯, 最后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組件的導(dǎo)航祟峦,可以看到這里使用了不同的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動態(tài)路由:
const routes = [
{
path:"/home",
component: home
},
{
path: "/about",
component: about
},
/*新增user路徑坯汤,配置了動態(tài)的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, 可以看到它們都導(dǎo)航到user組件,配置正確搀愧。
在動態(tài)路由中惰聂,怎么獲取到動態(tài)部分? 因為在組件中是可以顯示不同部分的咱筛,就是上面提到的“你的名字”搓幌。其實,當(dāng)整個vue-router 注入到根實例后迅箩,在組件的內(nèi)部溉愁,可以通過this.$route 來獲取到 router 實例。它有一個params 屬性饲趋,就是來獲得這個動態(tài)部分的拐揭。它是一個對象,屬性名奕塑,就是路徑中定義的動態(tài)部分 id, 屬性值就是router-link中to 屬性中的動態(tài)部分堂污,如123。使用vuex時龄砰,組件中想要獲取到state 中的狀態(tài)盟猖,是用computed 屬性,在這里也是一樣换棚,在組件中式镐,定義一個computed 屬性dynamicSegment, user 組件修改如下:
<template>
<div>
<h1>User</h1>
<div>我是user組件, 動態(tài)部分是{{dynamicSegment}}</div>
</div>
</template>
<script>
export default {
computed: {
dynamicSegment () {
return this.$route.params.id
}
}
}
</script>
這里還有最后一個問題固蚤,就是動態(tài)路由在來回切換時娘汞,由于它們都是指向同一組件,vue不會銷毀再創(chuàng)建這個組件夕玩,而是復(fù)用這個組件你弦,就是當(dāng)?shù)谝淮吸c擊(如:user123)的時候,vue 把對應(yīng)的組件渲染出來风秤,但在user123, user456點擊來回切換的時候鳖目,這個組件就不會發(fā)生變化了,組件的生命周期不管用了缤弦。這時如果想要在組件來回切換的時候做點事情领迈,那么只能在組件內(nèi)部(user.vue中)利用watch 來監(jiān)聽route 實現(xiàn)
<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>
嵌套路由
嵌套路由尘喝,主要是由我們的頁面結(jié)構(gòu)所決定的磁浇。當(dāng)我們進(jìn)入到home頁面的時候,它下面還有分類朽褪,如手機(jī)系列置吓,平板系列,電腦系列缔赠。當(dāng)我們點擊各個分類的時候衍锚,它還是需要路由到各個部分,如點擊手機(jī)嗤堰,它肯定到對應(yīng)到手機(jī)的部分戴质。
在路由的設(shè)計上,首先進(jìn)入到 home ,然后才能進(jìn)入到phone, tablet, computer. Phone, tablet, compute 就相當(dāng)于進(jìn)入到了home的子元素踢匣。所以vue 提供了childrens 屬性告匠,它也是一組路由,相當(dāng)于我們所寫的routes。
首先离唬,在home頁面上定義三個router-link 標(biāo)簽用于導(dǎo)航后专,然后再定義一個router-view標(biāo)簽,用于渲染對應(yīng)的組件男娄。router-link 和router-view 標(biāo)簽要一一對應(yīng)行贪。home.vue 組件修改如下:
<template>
<div>
<h1>home</h1>
<!-- router-link 的to屬性要注意,路由是先進(jìn)入到home,然后才進(jìn)入相應(yīng)的子路由如 phone,所以書寫時要把 home 帶上 -->
<p>
<router-link to="/home/phone">手機(jī)</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",
// 下面這個屬性也不少,因為崭捍,我們是先進(jìn)入home頁面尸折,才能進(jìn)入子路由
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'
}
]
這時當(dāng)我們點擊home 時,它下面出現(xiàn)手機(jī)等字樣殷蛇,但沒有任何對應(yīng)的組件進(jìn)行顯示实夹,這通常不是我們想要的。要想點擊home時粒梦,要想渲染相對應(yīng)的子組件亮航,那還需要配置一條路由。當(dāng)進(jìn)入到home 時匀们,它在children中對應(yīng)的路由path 是空 ‘’缴淋,完整的childrens 如下:
children: [
{
path: "phone",
component: phone
},
{
path: "tablet",
component: tablet
},
{
path: "computer",
component: computer
},
// 當(dāng)進(jìn)入到home時,下面的組件顯示
{
path: "",
component: phone
}
]
命名路由
命名路由,很簡單重抖,因為根據(jù)名字就可以知道露氮,這個路由有一個名字,那就直接給這個路由加一個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> // 當(dāng)使用對象作為路由的時候,to前面要加一個冒號,表示綁定
編程式導(dǎo)航:這主要應(yīng)用到按鈕點擊上恨统。當(dāng)點擊按鈕的時候叁扫,跳轉(zhuǎn)另一個組件, 這只能用代碼,調(diào)用rourter.push() 方法畜埋。 當(dāng)們把router 注入到根實例中后莫绣,組件中通過 this.$router 可以獲取到router, 所以在組件中使用
this.$router.push("home"), 就可以跳轉(zhuǎn)到home界面