06 . Vue路由簡介,原理,實現及巢狀路由,動態路由,程式設計式導航
阿新 • • 發佈:2020-11-19
#### 路由概念
> 路由的本質就是一種對應關係,比如說我們在url地址中輸入我們要訪問的url地址之後,瀏覽器要去請求這個url地址對應的資源。
> 那麼url地址和真實的資源之間就有一種對應的關係,就是路由。
`路由分為前端路由和後端路由`
```go
/*
1).後端路由是由伺服器端進行實現,並完成資源的分發.
概念: 根據不同的URL請求,返回不同的內容
本質: URL請求地址與伺服器資源之間的對應關係
2).前端路由是依靠hash值(錨鏈接)的變化進行實現
概念: 根據不同的事件顯示不同的頁面內容,即事件與事件處理函式之間的對應關係.
前端路由主要做監聽事件並分發執行事件處理函式
後端路由效能相對前端路由來說較低
*/
```
![](https://img2020.cnblogs.com/blog/1871335/202011/1871335-20201119191441320-1628059778.png)
##### SPA
`Single Page Application`
```go
/*
後端渲染(存在效能問題)
Ajax前端渲染(前端渲染提高效能,但是不支援瀏覽器的前進後退操作)
SPA(Single Page Applicationn) 單頁面應用程式:
整個網站只有一個頁面,內容的變化通過Ajax區域性更新實現,同時支援瀏覽器位址列的前進和後退操作.
SPA實現原理之一: 基於URL地址的hash(hash的變化會導致瀏覽器記錄訪問歷史的變化,但是hash的變化不會觸發新的URL請求)
在實現SPA的過程中,最核心技術點就是前端路由
*/
```
##### 前端路由
> 前端路由是基於hash值的變化進行實現的(比如點選頁面中的選單或者按鈕改變URL的hash值,根據hash值的變化來控制組件的切換)
> 核心實現依靠一個不同的使用者事件,即監聽hash值變化的事件,顯示不同的頁面內容.
`本質: 使用者事件與事件處理函式之間的對應關係`
![](https://img2020.cnblogs.com/blog/1871335/202011/1871335-20201119191431713-306800663.png)
#### 實現簡易前端路由
`基於URL的hash實現(點選選單的時候改變URL的hash,根據hash的變化控制組件的切換)`
##### 模擬路由
```vue
Document
主頁
科技
財經
娛樂
```
`核心思路`
> 在頁面中有一個vue例項物件,vue例項物件中有四個元件,分別是tab欄切換需要顯示的元件內容
> 在頁面中有四個超連結,如下:
```vue
主頁
科技
財經
娛樂
```
> 當我們點選這些超連結的時候,就會改變url地址中的hash值,當hash值被改變時,就會觸發onhashchange事件
> 在觸發onhashchange事件的時候,我們根據hash值來讓不同的元件進行顯示:
```vue
window.onhashchange = function() {
// 通過 location.hash 獲取到最新的 hash 值
console.log(location.hash);
switch(location.hash.slice(1)){
case '/zhuye':
//通過更改資料comName來指定顯示的元件
//因為 ,元件已經綁定了comName
vm.comName = 'zhuye'
break
case '/keji':
vm.comName = 'keji'
break
case '/caijing':
vm.comName = 'caijing'
break
case '/yule':
vm.comName = 'yule'
break
}
}
```
#### Vue Router簡介
> 它是一個Vue.js官方提供的路由管理器。是一個功能更加強大的前端路由器,推薦使用。
> Vue Router和Vue.js非常契合,可以一起方便的實現SPA(single page web application,單頁應用程式)應用程式的開發。
> Vue Router依賴於Vue,所以需要先引入Vue,再引入Vue Router
##### Vue Router特性
```go
/*
支援H5歷史模式或者hash模式
支援巢狀路由
支援路由引數
支援程式設計式路由
支援命名路由
支援路由導航守衛
支援路由過渡動畫特效
支援路由懶載入
支援路由滾動行為
*/
```
#### Vue Router的使用
##### 步驟
```go
/*
1. 引入相關的庫檔案
2. 新增路由連結
3. 新增路由填充位
4. 定義路由元件
5. 配置路由規則並建立路由例項
6. 把路由掛載到Vue根例項中
補充:
路由重定向:可以通過路由重定向為頁面設定預設展示的元件
在路由規則中新增一條路由規則即可,如下:
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//path設定為/表示頁面最初始的地址 / ,redirect表示要被重定向的新地址,設定為一個路由即可
{ path:"/",redirect:"/user"},
{ path: "/user", component: User },
{ path: "/login", component: Login }
]
})
*/
```
`A.匯入js檔案`
```vue
```
`B.新增路由連結:是路由中提供的標籤,預設會被渲染為a標籤,to屬性預設被渲染為href屬性,
to屬性的值會被渲染為#開頭的hash地址`
```vue
User
Login
```
`C.新增路由填充位(路由佔位符)`
```vue
```
`D.定義路由元件`
```vue
var User = { template:"This is User" }
var Login = { template:"This is Login" }
```
`E.配置路由規則並建立路由例項`
```vue
var myRouter = new VueRouter({
//routes是路由規則陣列
routes:[
//每一個路由規則都是一個物件,物件中至少包含path和component兩個屬性
//path表示 路由匹配的hash地址,component表示路由規則對應要展示的元件物件
{path:"/user",component:User},
{path:"/login",component:Login}
]
})
```
`F.將路由掛載到Vue例項中`
```vue
new Vue({
el:"#app",
//通過router屬性掛載路由物件
router:myRouter
})
```
`Example`
```vue
Document
User
Register
```
##### 路由重定向
> 路由重定向指的是: 使用者在訪問A的時候,強制使用者跳轉到地址c,從而展示特定的元件頁面;
>
> 通過路由規則的redirect屬性,指定一個新的路由地址,可以很方便的設定路由重定向.
```vue
// 建立路由例項物件
var router = new VueRouter({
// 所有的路由規則
routes: [
// 其中,path表示需要被重定向的原地址, redirect表示將要被重定向到的新地址
{path: '/', redirect: '/User'},
{path: '/user', component: '/User'},
{path: '/register', component: Register}
]
})
```
#### 巢狀路由
##### 巢狀路由功能
```go
/*
點選父級路由連結顯示模板內容
模板內容中又有子級路由連結
點選子級路由連結顯示子級模板內容
*/
```
##### 巢狀路由的概念
> 當我們進行路由的時候顯示的元件中還有新的子級路由連結以及內容。
>
> 巢狀路由最關鍵的程式碼在於理解子級路由的概念:
> 比如我們有一個/login的路由
> 那麼/login下面還可以新增子級路由,如:
> /login/account
> /login/phone
`參考程式碼如下`
```vue
var User = { template: "This is User" }
//Login元件中的模板程式碼裡面包含了子級路由連結以及子級路由的佔位符
var Login = { template: `
賬號密碼登入
掃碼登入
` }
//定義兩個子級路由元件
var account = { template:"賬號:
密碼:"}; var phone = { template:"
```
`子級路由模板`
```vue
/*
子級路由連結
子級路由填充位
*/
const Register = {
template: `
Tab1
Tab2
}
```
`父路由通過children屬性配置子級路由`
```vue
const router = new VueRouteer({
routes: [
{ path: '/user',component: User},
{
path: '/register',
component: Register,
// 通過children屬性,為/register新增子路由規則
children: [
{path: '/',redirect: '/user'},
{path: '/user', component: User},
{path: '/register', component: Register}
]
}
]
})
```
`Example`
```vue
Document
User
Register
```
#### 動態路由
##### 動態路由匹配
```go
var User = { template:"使用者:{{$route.params.id}}"}
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//通過/:引數名 的形式傳遞引數
{ path: "/user/:id", component: User },
]
})
```
`注意`
```go
// 如果使用$route.params.id來獲取路徑傳參的資料不夠靈活。
// 1.我們可以通過props來接收引數
var User = {
props:["id"],
template:"使用者:{{id}}"
}
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//通過/:引數名 的形式傳遞引數
//如果props設定為true,route.params將會被設定為元件屬性
{ path: "/user/:id", component: User,props:true },
]
})
// 2.還有一種情況,我們可以將props設定為物件,那麼就直接將物件的資料傳遞給
元件進行使用
var User = {
props:["username","pwd"],
template:"使用者:{{username}}---{{pwd}}"
}
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//通過/:引數名 的形式傳遞引數
//如果props設定為物件,則傳遞的是物件中的資料給元件
{ path: "/user/:id", component: User,props:{username:"jack",pwd:123} },
]
})
// 3.如果想要獲取傳遞的引數值還想要獲取傳遞的物件資料,那麼props應該設定為
函式形式。
var User = {
props:["username","pwd","id"],
template:"使用者:{{id}} -> {{username}}---{{pwd}}"
}
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//通過/:引數名 的形式傳遞引數
//如果props設定為函式,則通過函式的第一個引數獲取路由物件
//並可以通過路由物件的params屬性獲取傳遞的引數
//
{ path: "/user/:id", component: User,props:(route)=>{
return {username:"jack",pwd:123,id:route.params.id}
}
},
]
})
```
`Example`
```vue
Document
User1
User2
User3
Register
```
##### 路由元件傳遞引數
```go
/*
$route與對應路由形式高度耦合,不夠靈活,所以可以使用props將元件和路由解耦
*/
```
`1. props的值為布林型別`
```vue
const router = new VueRouter({
routes: [
// 如果props被設定為true, route.params將會被設定為元件屬性
[ path: '/user/:id',component: User,props:true ]
]
const User = [
props: ['id'], // 使用props接受路由引數
template: '使用者ID: {{ id }}' // 使用路由引數
]
})
```
`Example1`
```vue
Document
User1
User2
User3
Register
```
`props的值為物件型別`
```vue
const router = new VueRouter({
routes: [
// 如果props被設定為true, route.params將會被設定為元件屬性
[ path: '/user/:id',component: User,props: {uname:'lisi',age:12} ]
]
const User = [
props: ['uname','age'], // 使用props接受路由引數
template: '使用者ID: {{ uname + '----' + age }}' // 使用路由引數
]
})
```
`props的值為函式型別`
```vue
const router = new VueRouter({
routes: [
// 如果props是一個函式,則這個函式接受route物件為自己的形參
[ path: '/user/:id',component: User,props: route => ({uname: 'zs',age: 20, id: route.params.id})
]
})
const User = [
props: ['uname','age','id'], // 使用props接受路由引數
template: 'User
router.push({name:'user',params: {id:123}})
````
`Example`
```vue
var myRouter = new VueRouter({
//routes是路由規則陣列
routes: [
//通過name屬性為路由新增一個別名
{ path: "/user/:id", component: User, name:"user"},
]
})
// 添加了別名之後,可以使用別名進行跳轉
User
User
// 還可以程式設計式導航
myRouter.push( { name:'user' , params: {id:123} } )
```
`Example1`
```vue
Document
User1
User2
User3
Register
```
#### 程式設計式導航
`頁面導航的兩種方式`
> A.宣告式導航:通過點選連結的方式實現的導航
> B.程式設計式導航:呼叫js的api方法實現導航
##### Vue-Router常見導航方式
```go
/*
Vue-Router中常見的導航方式:
this.$router.push("hash地址");
this.$router.push("/login");
this.$router.push({ name:'user' , params: {id:123} });
this.$router.push({ path:"/login" });
this.$router.push({ path:"/login",query:{username:"jack"} });
this.$router.go( n );//n為數字,參考history.go
this.$router.go( -1 );
*/
```
#### 後臺管理案例
點選左側的"使用者管理","許可權管理","商品管理","訂單管理","系統設定"都會出現對應的元件並展示內容
其中"使用者管理"元件展示的效果如上圖所示,在使用者管理區域中的詳情連結也是可以點選的,點選之後將會顯示使用者詳情資訊。
案例思路:
```go
/*
1).先將素材資料夾中的11.基於vue-router的案例.html複製到我們自己的資料夾中。
看一下這個檔案中的程式碼編寫了一些什麼內容,
這個頁面已經把後臺管理頁面的基本佈局實現了
2).在頁面中引入vue,vue-router
3).建立Vue例項物件,準備開始編寫程式碼實現功能
4).希望是通過元件的形式展示頁面的主體內容,而不是寫死頁面結構,所以我們可以定義一個根元件:
*/
```
```vue
//只需要把原本頁面中的html程式碼設定為元件中的模板內容即可
const app = {
template:`
傳智後臺管理系統
```
6).此時我們開啟頁面應該就可以得到一個VueRouter路由出來的根元件了
我們需要在這個根元件中繼續路由實現其他的功能子元件
先讓我們更改根元件中的模板:更改左側li為子級路由連結,並在右側內容區域新增子級元件佔位符
```vue
const app = {
template:`
........
.......
`
}
```
然後,我們要為子級路由建立並設定需要顯示的子級元件
```vue
//建議建立的元件首字母大寫,和其他內容區分
const Users = {template:`
`}
```
~~~
8.當用戶列表展示完畢之後,我們可以點選列表中的詳情來顯示使用者詳情資訊,首先我們需要建立一個元件,用來展示詳情資訊
```vue
const UserInfo = {
props:["id"],
template:`
`,
methods:{
goDetail(id){
this.$router.push("/userinfo/"+id);
}
This is Login
密碼:"}; var phone = { template:"
掃我二維碼
"}; var myRouter = new VueRouter({ //routes是路由規則陣列 routes: [ { path:"/",redirect:"/user"}, { path: "/user", component: User }, { path: "/login", component: Login, //通過children屬性為/login新增子路由規則 children:[ { path: "/login/account", component: account }, { path: "/login/phone", component: phone }, ] } ] }) var vm = new Vue({ el: '#app', data: {}, methods: {}, router:myRouter }); ``` ##### 巢狀路由用法 `父路由元件模板` ```vue /* 父級路由連結 父元件路由填充位 */
Register 元件
User 元件 -- 使用者id為: {{ id }} -- 姓名為:{{ uname }} -- 年齡為: {{ age }}
' // 使用路由引數 ] }) ``` #### 命名路由 `命名路由:給路由取別名` ````vue const router = new VueRouter({ routes: [ { path: '/user/:id', name: 'user', component: User } ] })- 使用者管理
- 許可權管理
- 商品管理
- 訂單管理
- 系統設定
使用者管理 許可權管理 商品管理 訂單管理 系統設定
使用者管理
`} const Access = {template:`許可權管理
`} const Goods = {template:`商品管理
`} const Orders = {template:`訂單管理
`} const Systems = {template:`系統管理
`} //新增子元件的路由規則 const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter }) ``` 7).展示使用者資訊列表: A.為Users元件新增私有資料,並在模板中迴圈展示私有資料 ~~~vue const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`使用者管理
編號 | 姓名 | 年齡 | 操作 |
---|---|---|---|
{{item.id}} | {{item.name}} | {{item.age}} | 詳情 |
使用者詳情
檢視 {{id}} 號使用者資訊
`, methods:{ goBack(){ //當用戶點選按鈕,後退一頁 this.$router.go(-1); } } } ``` 然後我們需要設定這個元件的路由規則 ```vue const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, //新增一個/userinfo的路由規則 { path:"/userinfo/:id",component:UserInfo,props:true}, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter }) ``` 再接著給使用者列表中的詳情a連線新增事件 ```vue const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`使用者管理
編號 | 姓名 | 年齡 | 操作 |
---|---|---|---|
{{item.id}} | {{item.name}} | {{item.age}} | 詳情 |