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