本篇文章給大家?guī)鞻ue-Router路由的相關(guān)知識,Vue Router是Vue.js 官方的路由管理器。它和Vue.js的核心深度集成,可以非常方便的用于SPA應(yīng)用程序的開發(fā)。希望對大家有幫助。
一.速識概念:
1. 后端路由:
1.根據(jù)不同的用戶URL請求,返回不同的內(nèi)容,本質(zhì)上是URL請求地址與服務(wù)器資源之間的對應(yīng)關(guān)系。
2.但是呢,后端渲染存在性能問題。
2. 前端路由:
3.所以出現(xiàn)了Ajax前編渲染 ,前端渲染能提高性能,但是不支持瀏覽器的前進(jìn)后退操作。
4.這時(shí)又出現(xiàn)了SPA (Single Page Application)單頁面應(yīng)用程序,整個(gè)網(wǎng)站只有一個(gè)頁面,內(nèi)容的變化通過Ajax局部更新實(shí)現(xiàn)、同時(shí)支持瀏覽器地址欄的前進(jìn)和后退操作。
5.SPA實(shí)現(xiàn)原理之一就是基于URL地址的 hash (hash的變化會導(dǎo)致瀏覽器記錄訪問歷史的變化、但是hash的變化不會觸發(fā)新的URL請求) 。在實(shí)現(xiàn)SPA過程中, 其中最核心的技術(shù)點(diǎn)就是前端路由。
6.前端路由就是根據(jù)不同的用戶事件,顯示不同的頁面內(nèi)容。本質(zhì)就是用戶事件與事件處理函數(shù)之間的對應(yīng)關(guān)系。
3.Vue Router:
這是官方使用文檔鏈接。:https://router.vuejs.org/zh/guide/#javascript
Vue Router是Vue.js 官方的路由管理器。它和Vue.js的核心深度集成,可以非常方便的用于SPA應(yīng)用程序的開發(fā)。
它的功能如下:
1.支持HTML5歷史模式或hash模式。
2.支持嵌套路由。
3.支持路由參數(shù)。
4.支持編程式路由。
5.支持命名路由。
二.基本使用:
前提:
下面將會以一個(gè)HTML單頁面演示Vue Router的基本使用步驟。在vue項(xiàng)目里也是一樣的原理。當(dāng)前單頁面基本代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <p id="app"> </p> <script> const app = new Vue({ el:"#app", data: {} }) </script> </body> </html>
可以看到什么都沒有:
下面開始使用的具體步驟:
1.引入相關(guān)的文件:
單頁面肯定得先導(dǎo)入vue文件與vue-router文件,這樣我們才能夠使用路由。
<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
2.添加路由鏈接:
以下是一個(gè)vue提供的標(biāo)簽,默認(rèn)會被渲染為a標(biāo)簽。其中有一個(gè)to屬性,這個(gè)to屬性會被渲染為href屬性,默認(rèn)值被渲染為 # 開頭的hash地址。簡單來說就是當(dāng)用戶點(diǎn)擊不同時(shí)跳轉(zhuǎn)不同內(nèi)容,而這個(gè)標(biāo)簽就是用戶要點(diǎn)擊的東西,相當(dāng)于a標(biāo)簽嘛。
<router-link to="/..." >...</router-link>
給我們的單頁面上加一個(gè)page1和一個(gè)page2的鏈接:
<p id="app"> <router-link to="/page1">Page1</router-link> <router-link to="/page2">Page2</router-link> </p>
3.添加路由填充位:
下面這個(gè)標(biāo)簽叫路由填充位,就是說未來通過我們的路由規(guī)則匹配到的組件,將會被渲染到 router-view所在位置。簡單來說,就是用戶點(diǎn)擊路由鏈接,那得跳轉(zhuǎn)內(nèi)容吧,我們知道的是肯定不是整個(gè)頁面都跳轉(zhuǎn),只是頁面內(nèi)相關(guān)的局部發(fā)生內(nèi)容改變,這個(gè)局部就是router-view所在顯示的區(qū)域。
<router-view></router-view>
給我們的頁面添加:
<p id="app"> <router-link to="/page1">Page1</router-link> <router-link to="/page2">Page2</router-link> <router-view></router-view> </p>
4.定義路由組件:
既然要顯示不同的內(nèi)容,那肯定是用一個(gè)組件保存一份內(nèi)容。下面我們給單頁面定義page1,page2這兩個(gè)組件。
<script> const Page1 = { template: '<h1>我是北極光之夜1號</h1>' } const Page2 = { template: '<h1>我是北極光之夜2號</h1>' } const app = new Vue({ el:"#app", data: {} }) </script>
5.配置路由規(guī)則井創(chuàng)建路由實(shí)例:
routes是路由規(guī)則數(shù)組。每個(gè)路由規(guī)則都是一個(gè)配置對象, 其中至少包含path 和component 兩個(gè)屬性,path 表示當(dāng)前路由規(guī)則匹配的hash 地址,component 表示當(dāng)前路由規(guī)則對應(yīng)要展示的組件。簡單來說就是你點(diǎn)擊那個(gè)鏈接對應(yīng)的地址要對應(yīng)的是哪個(gè)內(nèi)容的組件。path跟router-link標(biāo)簽里的地址要一樣,別寫錯了。
const router = new VueRouter({ routes: [ {path:'/page1',component:Page1 }, {path:'/page2',component:Page2 } ] })
6.把路由掛載到Vue根實(shí)例中:
為了能夠讓路由規(guī)則生效,必須把路由對象掛載到vue 實(shí)例對象上。
const app = new Vue({ el:"#app", data: {}, router })
7.效果與單頁面代碼:
以上我們就大工告成~
上面的完整代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 導(dǎo)入vue文件 --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> </head> <body> <p id="app"> <router-link to="/page1">Page1</router-link> <router-link to="/page2">Page2</router-link> <router-view></router-view> </p> <script> const Page1 = { template: '<h1>我是北極光之夜1號</h1>' } const Page2 = { template: '<h1>我是北極光之夜2號</h1>' } const router = new VueRouter({ routes: [ {path:'/page1',component:Page1 }, {path:'/page2',component:Page2 } ] }) const app = new Vue({ el:"#app", data: {}, router }) </script> </body> </html>
三.路由重定向:
路由重定向指的是用戶在訪問地址A的時(shí)候,強(qiáng)制用戶跳轉(zhuǎn)到地址B,從而展示特定的組件頁面。
通過路由規(guī)則的redirect屬性,指定一個(gè)新的路由地址,可以很方便地設(shè)置路由的重定向。
{path:'/..',redirect: '/...'}
其中path表示重定向的原地址,redirect表示新地址。
比如第二大點(diǎn)的案例中,剛打開的頁面如下,在根目錄,但我們想一進(jìn)入就顯示page1,那就給根目錄重定向。
修改路由規(guī)則如下:
const router = new VueRouter({ routes: [ {path:'/page1',component:Page1 }, {path:'/page2',component:Page2 }, {path:'/',redirect:'/page1'} ] })
看效果,我沒點(diǎn)擊就默認(rèn)進(jìn)入page1了:
四.嵌套路由:
功能如下:
- 點(diǎn)擊父級路由鏈接顯示模板內(nèi)容。
- 模板內(nèi)容中又有子級路由鏈接。
- 點(diǎn)擊子級路由鏈接顯示子級模板內(nèi)容。
比如我們改進(jìn)第二大點(diǎn)的案例,當(dāng)點(diǎn)擊page2顯示page2內(nèi)容時(shí),page2里又有兩個(gè)子路由連接,star和moon,當(dāng)點(diǎn)擊其中一個(gè)鏈接時(shí)又能顯示對應(yīng)的star或moon內(nèi)容。
1.首先給page2組件添加兩個(gè)子路由鏈接:
const Page2 = { template: ` <p> <h1>我是北極光之夜2號</h1> <hr/> <router-link to="/page2/star">Star</router-link> <router-link to="/page2/moon">Moon</router-link> <hr/> </p>` }
此時(shí)頁面也把顯示子路由鏈接出來了:
2.給兩個(gè)子路由鏈接添加路由填充位:
const Page2 = { const Page2 = { template: ` <p> <h1>我是北極光之夜2號</h1> <hr/> <router-link to="/page2/star">Star</router-link> <router-link to="/page2/moon">Moon</router-link> <hr/> <router-view></router-view> </p>` }
3.設(shè)置兩個(gè)子組件star與moon的內(nèi)容:
const Star = { template: '<h2>我是北極光之夜2號下的star</h2>' } const Moon = { template: '<h2>我是北極光之夜2號下的Moon</h2>' }
4.配置路由規(guī)則:
page2的規(guī)則除了path和component屬性外,再添加一個(gè)children屬性,這個(gè)屬性以數(shù)組表示,數(shù)組里存放其子路由的規(guī)則,其規(guī)則也是一樣的,套娃套娃。
const router = new VueRouter({ routes: [ {path:'/page1',component:Page1 }, { path:'/page2', component:Page2, children: [ {path: '/page2/star',component:Star}, {path: '/page2/moon',component:Moon} ] } ] })
5.效果與單頁面代碼:
完整代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 導(dǎo)入vue文件 --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> </head> <body> <p id="app"> <router-link to="/page1">Page1</router-link> <router-link to="/page2">Page2</router-link> <router-view></router-view> </p> <script> const Page1 = { template: '<h1>我是北極光之夜1號</h1>' } const Page2 = { template: ` <p> <h1>我是北極光之夜2號</h1> <hr/> <router-link to="/page2/star">Star</router-link> <router-link to="/page2/moon">Moon</router-link> <hr/> <router-view></router-view> </p>` } const Star = { template: '<h2>我是北極光之夜2號下的star</h2>' } const Moon = { template: '<h2>我是北極光之夜2號下的Moon</h2>' } const router = new VueRouter({ routes: [ {path:'/page1',component:Page1 }, { path:'/page2', component:Page2, children: [ {path: '/page2/star',component:Star}, {path: '/page2/moon',component:Moon} ] } ] }) const app = new Vue({ el:"#app", data: {}, router }) </script> </body> </html>
五. 動態(tài)路由匹配:
1.動態(tài)匹配路由基本使用:
如果某些路由規(guī)則的一部分是一樣的,只有另一部分是動態(tài)變化的,那我們可以把這些動態(tài)變化的部分形成路由參數(shù),這些參數(shù)就叫做動態(tài)路由匹配。簡單來說,你先看下面這些路由鏈接,它們都有/page/,就是后面不一樣:
<router-link to="/page/1">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link>
那該咋配置路由呢?這樣嗎:
const router = new VueRouter({ routes: [ {path:'/page/1',component:Page}, {path:'/page/2',component:Page}, {path:'/page/3',component:Page} ] })
這樣萬一有很多一個(gè)個(gè)寫豈不是太麻煩了,所以引入?yún)?shù),在動態(tài)改變的部分定義為參數(shù),參數(shù)前面有一個(gè)冒號,那上面可簡寫成如下,動態(tài)部分設(shè)為參數(shù) :id 。
const router = new VueRouter({ routes: [ {path:'/page/:id',component:Page }, ] })
在組件可以通過以下語法獲取當(dāng)前路由的參數(shù):
$router.params.參數(shù)名稱
好,再次修改第二大點(diǎn)的案例完成動態(tài)路由匹配:
1.定義路由鏈接:
<p id="app"> <router-link to="/page/1">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link> <router-view></router-view> </p>
2.動態(tài)配置路由,參數(shù)id:
const router = new VueRouter({ routes: [ {path:'/page/:id',component:Page1 }, ] })
3.設(shè)置組件內(nèi)容,并顯示當(dāng)前路由的參數(shù):
const Page1 = { template: '<h1>我是北極光之夜1號,當(dāng)前id為:{{$route.params.id}}</h1>' }
看效果:
2.路由組件傳參:
上面的$route與對應(yīng)路由形成高度耦合,不夠靈活啊,所以可以使用props將組件和路由解耦。簡單來說,好像也沒什么說的,直接看下面實(shí)例就能理解了。
2.1 當(dāng)props為布爾類型:
const router = new VueRouter({ routes: [ // 設(shè)置props,如果props為true,router.params會被設(shè)置為組件屬性 {path:'/page/:id',component:Page1,props: true }, ] }) const Page1 = { // 這時(shí)就通過props接收參數(shù),快速簡潔的接收參數(shù)id和使用它 props: ['id'], template: '<h1>我是北極光之夜1號,當(dāng)前id為:{{id}}</h1>' }
能達(dá)到一樣的效果,且更靈活了,上面記得反過來,先定義組件才配置路由規(guī)則,只是為了直觀才這樣寫:
2.2 當(dāng)props為對象類型:
const Page1 = { // 這時(shí)就通過props接收參數(shù),快速簡潔的接收參數(shù)對象 并顯示 props: ['name','age'], template: `<h1>我是北極光之夜1號,當(dāng)前id為:{{id}} <hr/> 姓名為:{{name}} ,年齡為:{{age}} </h1>` } const router = new VueRouter({ routes: [ // props為一個(gè)參數(shù)對象,它會原樣設(shè)置為組件屬性, // 里面的自定義的參數(shù)都能傳過去,但是id傳不了了 {path:'/page/:id',component:Page1 , props: {name:'auroras',age: 18} } ] })
效果,對象props對象里的能獲取,id就不行了:
2.3 當(dāng)props為函數(shù)類型:
這個(gè)就什么都能獲取。
const Page1 = { // 這時(shí)就通過props接收參數(shù),快速簡潔的接收參數(shù) props: ['name','age','id'], template: `<h1>我是北極光之夜1號,當(dāng)前id為:{{id}} <hr/> 姓名為:{{name}} ,年齡為:{{age}} </h1>` } const router = new VueRouter({ routes: [ // props為函數(shù),這個(gè)對象接收router對象為自己形參, // 里面的自定義的參數(shù)和id都能傳過去 {path:'/page/:id', component:Page1 , props: router => ({id: router.params.id,name:'auroras',age: 18}) } ] })
效果:
當(dāng)前完整代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 導(dǎo)入vue文件 --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> </head> <body> <p id="app"> <router-link to="/page/1">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link> <router-view></router-view> </p> <script> const Page1 = { // 這時(shí)就通過props接收參數(shù),快速簡潔的接收參數(shù)對象 props: ['name','age','id'], template: `<h1>我是北極光之夜1號,當(dāng)前id為:{{id}} <hr/> 姓名為:{{name}} ,年齡為:{{age}} </h1>` } const router = new VueRouter({ routes: [ // props為函數(shù),這個(gè)對象接收router對象為自己形參, // 里面的自定義的參數(shù)和id都能傳過去 {path:'/page/:id', component:Page1 , props: router => ({id: router.params.id,name:'auroras',age: 18}) } ] }) const app = new Vue({ el:"#app", data: {}, router }) </script> </body> </html>
六.Vue-Router命名路由:
為更加方便的表示路由的路徑,可以給路由規(guī)則起一個(gè)別名, 即為“命名路由”。繼續(xù)改進(jìn)上面的案例講解用法:
1.首先給路由規(guī)則加一個(gè)name屬性,這個(gè)就是別名:
const router = new VueRouter({ routes: [ { name: 'user', path:'/page/:id', component:Page1 , props: router => ({id: router.params.id,name:'auroras',age: 18}) } ] })
2.在路由鏈接中使用:
<p id="app"> <router-link :to="{name:'user',params: {id: 1}}">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link> <router-view></router-view> </p>
我們把第一個(gè)路由鏈接改進(jìn),to前面加上冒號,其中name表示匹配的是哪個(gè)路由規(guī)則,params表示要傳遞的參數(shù),看下面是一樣的效果:
七.編程式導(dǎo)航:
-
聲明式導(dǎo)航:首先聲明式導(dǎo)航是指用戶通過點(diǎn)擊鏈接完成導(dǎo)航的方式,比如點(diǎn)擊a標(biāo)簽或者路由鏈接這些完成的跳轉(zhuǎn)。
-
編程式導(dǎo)航:編程式導(dǎo)航就是說跳轉(zhuǎn)是因?yàn)槲尹c(diǎn)擊它,它不是鏈接,但是它在JavaScript里調(diào)用了某個(gè)API也實(shí)現(xiàn)了跳轉(zhuǎn)。
- 常用的編程式導(dǎo)航API如下:
this.$router.push('要跳轉(zhuǎn)的hash地址') this.$router.go(n)
push里直接放要跳轉(zhuǎn)的哈希地址,go方法實(shí)現(xiàn)前進(jìn)和后退,n代表數(shù)組,若n為1代表在歷史記錄中前進(jìn)一位,-1代表在歷史記錄中后退一位。
1. this.$router.push(’ '):
重寫一個(gè)案例,有page1、page2、page3三個(gè)路由鏈接,而在page3里有一個(gè)按鈕,這個(gè)按鈕的作用是點(diǎn)擊后返回顯示page1的內(nèi)容。這個(gè)按鈕可不是聲明式導(dǎo)航里的鏈接,就是一個(gè)按鈕。
1.定義普通的路由鏈接:
<p id="app"> <router-link :to="/page/1">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link> <router-view></router-view> </p>
2.定義3個(gè)組件內(nèi)容,其中給page3組件里放一個(gè)按鈕,并綁定點(diǎn)擊事件,在事件里通過API導(dǎo)航到page1:
const Page1 = { template: `<h1>我是北極光之夜1號</h1>` } const Page2 = { template: `<h1>我是北極光之夜2號</h1>` } const Page3 = { template: `<p> <h1>我是北極光之夜3號</h1> <button @click="goPage1">返回page1</button> </p>`, methods: { goPage1(){ this.$router.push('/page/1') } }, }
3.路由規(guī)則:
const router = new VueRouter({ routes: [ {path:'/page/1',component: Page1}, {path:'/page/2',component: Page2}, {path:'/page/3',component: Page3} ] })
4.看效果:
5.完整代碼:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 導(dǎo)入vue文件 --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> </head> <body> <p id="app"> <router-link to="/page/1">Page1</router-link> <router-link to="/page/2">Page2</router-link> <router-link to="/page/3">Page3</router-link> <router-view></router-view> </p> <script> const Page1 = { template: `<h1>我是北極光之夜1號</h1>` } const Page2 = { template: `<h1>我是北極光之夜2號</h1>` } const Page3 = { template: `<p> <h1>我是北極光之夜3號</h1> <button @click="goPage1">返回page1</button> </p>`, methods: { goPage1(){ this.$router.push('/page/1') } }, } const router = new VueRouter({ routes: [ {path:'/page/1',component: Page1}, {path:'/page/2',component: Page2}, {path:'/page/3',component: Page3} ] }) const app = new Vue({ el:"#app", data: {}, router }) </script> </body> </html>
不止href路徑,還可以有以下操作:
//字符串形式(路徑的名稱) router.push('/page1')
//對象的形式 router.push({path: '/page1'})
//也可以傳遞參數(shù),命名的路由 router.push({name: '/page1',parmas:{id: 1}})
//帶查詢參數(shù),變成 /page1?p=id //這個(gè)挺實(shí)用的,比如在某些音樂網(wǎng)頁,點(diǎn)擊歌單后要導(dǎo)航到另一個(gè)該歌單詳細(xì)界面,此時(shí)要帶id,詳細(xì)界面靠此id重新發(fā)送請求,請求詳細(xì)信息 router.push({parh: '/page1',query:{p: 'id' }})
2. this.$router.go(n):
改進(jìn)第1小點(diǎn)的案例,當(dāng)我page3跳到page1時(shí),page1里又有一個(gè)返回的按鈕。我們把n設(shè)置為-1,他就會在歷史記錄中后退一位,后退一位就是page3.
修改page1組件內(nèi)容:
const Page1 = { template: `<p> <h1>我是北極光之夜1號</h1> <button @click="goBack">返回</button> </p>`, methods: { goBack(){ this.$router.go(-1) } } }
效果:
【