[TOC]
## 1. 什么是路由
1. 對于普**通的網站**,所有的超鏈接都是URL地址,所有的URL地址都對應服務器上對應的資源;
2. 對于**單頁面應用程序**來說,主要通過URL中的hash(#號)來實現不同頁面之間的切換,同時,hash有一個特點:HTTP請求中不會包含hash相關的內容;**所以,單頁面程序中的頁面跳轉主要用hash實現;**
3. **在單頁面應用程序中,這種通過hash改變來切換頁面的方式,稱作前端路由(區別于后端路由);**
## 2. 在 vue 中使用 vue-router

url 變化:


1. 導入 vue-router 組件類庫:
~~~
<script src="./lib/vue-router-2.7.0.js"></script>
~~~
2. 使用 router-link 組件來導航
~~~
<!-- 2. 使用 router-link 組件來導航 -->
<router-link to="/login">登錄</router-link>
<router-link to="/register">注冊</router-link>
~~~
3. 使用 router-view 組件來顯示匹配到的組件
**路由控制這里的顯示**
~~~
<!-- 3. 使用 router-view 組件來顯示匹配到的組件 -->
<router-view></router-view>
~~~
4. 創建使用`Vue.extend`創建組件
~~~
? // 4.1 使用 Vue.extend 來創建登錄組件
? var login = Vue.extend({
? ? template: '<h1>登錄組件</h1>'
? });
?
? // 4.2 使用 Vue.extend 來創建注冊組件
? var register = Vue.extend({
? ? template: '<h1>注冊組件</h1>'
? });
~~~
5. 創建一個路由 router 實例,通過 routers 屬性來定義路由匹配規則
~~~
// 5. 創建一個路由 router 實例,通過 routers 屬性來定義路由匹配規則
? var router = new VueRouter({
? ? routes: [
? ? ? { path: '/login', component: login },
? ? ? { path: '/register', component: register }
? ? ]
? });
~~~
6. 使用 router 屬性來使用路由規則
~~~
// 6. 創建 Vue 實例,得到 ViewModel
? var vm = new Vue({
? ? el: '#app',
? ? router: router // 使用 router 屬性來使用路由規則
? });
~~~
整體
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<!-- 1. 安裝 vue-router 路由模塊 -->
<script src="./lib/vue-router-3.0.1.js"></script>
<style>
.router-link-active,
.myactive {
color: red;
font-weight: 800;
font-style: italic;
font-size: 80px;
text-decoration: underline;
background-color: green;
}
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(140px);
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s ease;
}
</style>
</head>
<body>
<div id="app">
<!-- <a href="#/login">登錄</a> -->
<!-- <a href="#/register">注冊</a> -->
<!-- router-link 默認渲染為一個a 標簽 -->
<router-link to="/login" tag="span">登錄</router-link>
<router-link to="/register">注冊</router-link>
<!-- 這是 vue-router 提供的元素,專門用來 當作占位符的,將來,路由規則,匹配到的組件,就會展示到這個 router-view 中去 -->
<!-- 所以: 我們可以把 router-view 認為是一個占位符 -->
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
<script>
// 組件的模板對象
var login = {
template: '<h1>登錄組件</h1>'
}
var register = {
template: '<h1>注冊組件</h1>'
}
/* Vue.component('login', {
template: '<h1>登錄組件</h1>'
}) */
// 2. 創建一個路由對象, 當 導入 vue-router 包之后,在 window 全局對象中,就有了一個 路由的構造函數,叫做 VueRouter
// 在 new 路由對象的時候,可以為 構造函數,傳遞一個配置對象
var routerObj = new VueRouter({
// route // 這個配置對象中的 route 表示 【路由匹配規則】 的意思
routes: [ // 路由匹配規則
// 每個路由規則,都是一個對象,這個規則對象,身上,有兩個必須的屬性:
// 屬性1 是 path, 表示監聽 哪個路由鏈接地址;
// 屬性2 是 component, 表示,如果 路由是前面匹配到的 path ,則展示 component 屬性對應的那個組件
// 注意: component 的屬性值,必須是一個 組件的模板對象, 不能是 組件的引用名稱;
// { path: '/', component: login },
{ path: '/', redirect: '/login' }, // 這里的 redirect 和 Node 中的 redirect 完全是兩碼事
{ path: '/login', component: login },
{ path: '/register', component: register }
],
linkActiveClass: 'myactive'
})
// 創建 Vue 實例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj // 將路由規則對象,注冊到 vm 實例上,用來監聽 URL 地址的變化,然后展示對應的組件
});
</script>
</body>
</html>
```
## router-view的name屬性
通過名稱,將組件渲染到對應的router-view上
1. 通過name屬性,標識router-view,不寫默認就是default
```
<router-view></router-view>
<router-view name="router1"></router-view>
```
2. components指定多個渲染,而不是component
```
routes: [ // 路由匹配規則
{ path: '/', redirect: '/login' }, // 這里的 redirect 和 Node 中的 redirect 完全是兩碼事
{ path: '/login', components: {default:login,router1:t1} },
{ path: '/register', components: {default:register,router2:t2} }
],
```
完整
```
<body>
<div id="app">
<router-link to="/login" tag="span">登錄</router-link>
<router-link to="/register">注冊</router-link>
<router-view></router-view>
<router-view name="router1"></router-view>
<router-view name="router2"></router-view>
</div>
<script>
// 組件的模板對象
var login = {
template: '<h1>登錄組件</h1>'
}
var register = {
template: '<h1>注冊組件</h1>'
}
var t1 = {
template: '<h1>router1我來了</h1>'
}
var t2 = {
template: '<h1>router2我來了</h1>'
}
var routerObj = new VueRouter({
routes: [ // 路由匹配規則
{ path: '/', redirect: '/login' }, // 這里的 redirect 和 Node 中的 redirect 完全是兩碼事
{ path: '/login', components: {default:login,router1:t1} },
{ path: '/register', components: {default:register,router2:t2} }
],
linkActiveClass: 'myactive'
})
// 創建 Vue 實例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router: routerObj // 將路由規則對象,注冊到 vm 實例上,用來監聽 URL 地址的變化,然后展示對應的組件
});
</script>
</body>
```

點擊注冊

## 設置路由高亮
## 設置路由切換動效
**## 在路由規則中定義參數**
**1.指定實參**
~~~
<router-link to="/login/12/ls">登錄</router-link>
~~~
**2. 通過 `this.$route.params`來獲取路由中的參數**:
~~~
var login = {
template: '<h1>登錄 --- {{ $route.params.id }} --- {{ $route.params.name }}</h1>',
data(){
return {
msg: '123'
}
},
created(){ // 組件的生命周期鉤子函數
console.log(this.$route.params.id)
}
}
~~~
**3. 在規則中定義路徑對應的參數**
在router對象中指定id和name
~~~
var router = new VueRouter({
routes: [
{ path: '/login/:id/:name', component: login },
{ path: '/register', component: register }
]
})
~~~
## **路由路徑中傳遞參數**
~~~
如果在路由中,使用 查詢字符串,給路由傳遞參數,則 不需要修改 路由規則的 path 屬性
~~~
<router-link to="/login?id=10&name=zs">登錄</router-link>
~~~
var login = {
template: '<h1>登錄 --- {{ $route.query.id }} --- {{ $route.query.name }}</h1>',
data(){
return {
msg: '123'
}
},
~~~
完整代碼
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<script src="./lib/vue-router-3.0.1.js"></script>
</head>
<body>
<div id="app">
<!-- 如果在路由中,使用 查詢字符串,給路由傳遞參數,則 不需要修改 路由規則的 path 屬性 -->
<router-link to="/login?id=10&name=zs">登錄</router-link>
<router-link to="/register">注冊</router-link>
<router-view></router-view>
</div>
<script>
var login = {
template: '<h1>登錄 --- {{ $route.query.id }} --- {{ $route.query.name }}</h1>',
data(){
return {
msg: '123'
}
},
created(){ // 組件的生命周期鉤子函數
// console.log(this.$route)
// console.log(this.$route.query.id)
}
}
var register = {
template: '<h1>注冊</h1>'
}
var router = new VueRouter({
routes: [
{ path: '/login', component: login },
{ path: '/register', component: register }
]
})
// 創建 Vue 實例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
// router: router
router
});
</script>
</body>
</html>
~~~
## **使用 `children` 屬性實現路由嵌套**

~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./lib/vue-2.4.0.js"></script>
<script src="./lib/vue-router-3.0.1.js"></script>
</head>
<body>
<div id="app">
<router-link to="/account">Account</router-link>
<! -- 第一個router站位 -->
<router-view></router-view>
</div>
<template id="tmpl">
<div>
<h1>這是 Account 組件</h1>
<router-link to="/account/login">登錄</router-link>
<router-link to="/account/register">注冊</router-link>
<! -- 第二個router站位 子router -->
<router-view></router-view>
</div>
</template>
<script>
// 組件的模板對象
var account = {
template: '#tmpl'
}
var login = {
template: '<h3>登錄</h3>'
}
var register = {
template: '<h3>注冊</h3>'
}
var router = new VueRouter({
routes: [
{
path: '/account',
component: account,
// 使用 children 屬性,實現子路由,同時,子路由的 path 前面,不要帶 / ,否則永遠以根路徑開始請求,這樣不方便我們用戶去理解URL地址
children: [
{ path: 'login', component: login },
{ path: 'register', component: register }
]
}
// { path: '/account/login', component: login },
// { path: '/account/register', component: register }
]
})
// 創建 Vue 實例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {},
router
});
</script>
</body>
</html>
~~~
## **路由前操作router.beforeEach**
> ?在前端路由跳轉中,路由跳轉前都是會經過beforeEach,而beforeEach可以通過next來控制到底去哪個路由。利用這一特點,可以做發送請求時的操作:例如:權限校驗(是否登錄、頁面是否存在)
beforeEach需要三個參數:
?**to: Route**: 即將要進入的目標路由對象
? ??????**from: Route**: 當前導航正要離開的路由
? ??????**next: Function**: 一定要調用該方法來?**resolve**?這個鉤子。執行效果依賴?next?方法的調用參數。
代碼:
```
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requireAuth)){ // 判斷該路由是否需要登錄權限
if (token) { // 判斷當前的token是否存在
next();
}
else {
next({
path: '/login',
// 將跳轉的路由path作為參數,登錄成功后跳轉到該路由(to原來的路由對象)
query: {redirect: to.fullPath}
})
}
}
else {
next();
}
});
```
但是除了用戶請求特定頁面時(攔截是否登錄),登錄后繼續請求這個頁面。正常登錄時不需要跳轉。
```
if(this.$route.query.redirect){
let redirect = this.$route.query.redirect;
this.$router.push(redirect);
}else{
this.$router.push('/');
}
```
## **router.push**
`router.push(location)?`: 用來進行頁面跳轉
* 除了使用 創建 a 標簽來定義導航鏈接,我們還可以借助 router 的實例方法,通過編寫代碼來實現。?
* 想要導航到不同的 URL,則使用 router.push 方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器后退按鈕時,則回到之前的 URL。當你點擊時,這個方法會在內部調用,所以說,點擊 等同于調用 router.push(…)。
聲明式:?`<router-link :to="..."> `
編程式:router.push(...)?
該方法的參數可以是一個字符串路徑,或者一個描述地址的對象。
~~~
// 字符串
router.push('home')
// 對象
this.$router.push({path: '/login?url=' + this.$route.path});
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 帶查詢參數,變成/backend/order?selected=2
this.$router.push({path: '/backend/order', query: {selected: "2"}});
// 設置查詢參數
this.$http.post('v1/user/select-stage', {stage: stage})
.then(({data: {code, content}}) => {
if (code === 0) {
// 對象
this.$router.push({path: '/home'});
}else if(code === 10){
// 帶查詢參數,變成/login?stage=stage
this.$router.push({path: '/login', query:{stage: stage}});
}
});
// 設計查詢參數對象
let queryData = {};
if (this.$route.query.stage) {
queryData.stage = this.$route.query.stage;
}
if (this.$route.query.url) {
queryData.url = this.$route.query.url;
}
this.$router.push({path: '/my/profile', query: queryData});
~~~
### replace
> 類型: boolean?
> 默認值: false?
設置 replace 屬性的話,當點擊時,會調用 router.replace() 而不是 router.push(),于是導航后不會留下 history 記錄。即使點擊返回按鈕也不會回到這個頁面。?
//加上replace: true后,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
~~~
this.$router.push({path: '/home', replace: true})
//如果是聲明式就是像下面這樣寫:
<router-link :to="..." replace></router-link>
// 編程式:
router.replace(...)
~~~
# 緩存
tab切換,緩存已渲染的數據,不會觸發生命mounted
頁面現在默認有緩存機制,如果不想緩存,添加meta: { notCache: true },并且name屬性要和vue頁面 export default 里的name屬性對應
- vue
- 為什么要學vue
- 數據雙向綁定
- vue指令
- v-bind創建HTML節點屬性
- v-on綁定事件
- v-cloak
- v-text
- v-for和key屬性
- v-if和v-show
- 案例1
- 自定義指令
- vue樣式
- vue生命周期
- vue過濾器
- 自定義鍵盤修飾符
- 跨域請求
- vue組件
- 組件基礎
- 引入vue文件組件
- 引入render函數作為組件
- 兄弟間組件通信
- 組件函數數據傳遞練習
- 路由
- 數據監聽
- webpack
- vue校驗
- vue筆記
- form表單中input前部分默認輸入,切不可修改
- mixins
- 部署到nginx
- scope
- render
- 下載文件
- vue動態組件
- axios
- Promise
- vue進階
- node-vue-webpack搭建
- vue事件
- 插槽
- vuex
- vuex基礎
- vuex命名空間
- HTML遞歸?
- this.$nextTick異步更新dom
- elementui
- table
- 修改element ui樣式
- form
- 優質博客
- vuex state數據與form元素綁定
- es6
- Promise