前端路由
看到這里可能有朋友有疑惑了,前端也有路由嗎?這些難道不應該是在后端部分操作的嗎?確實是這樣,但是現在前后端分離后,加上現在的前端框架的實用性,為的就是均衡前后端的工作量,所以在前端也有了路由,減輕了服務器對這方面的判斷,在前端做好路由分發之后,后端就只需要寫API接口了,更着重於數據交互,邏輯上的代碼編寫了
單頁面應用
那么,既然有前端路由,每個路由是不是都要單寫一個頁面呢?不需要的,現在都提倡單頁面應用
什么是單頁面應用呢
單頁面應用,即 single page application ,簡稱SPA ,所有的路由其實都只在一個頁面上完成,這種就叫單頁面應用,我們不需要每個路由對應一個頁面去編寫
為什么要用單頁面應用
1.傳統的根據路由切換頁面,都是立即切換,如果切換的網絡資源很多的話,加載需要很久,用戶體驗很不好,並且寫的頁面越多,也越不好管理,可能還會有很多重復的代碼出現,到后期更新迭代后,頁面越來越多,這樣會產生更多的資源
2.SPA可以完美解決以上的問題,並且數據切換時只是局部切換,且並不會立即切換,而是在某個合適的時間用ajax異步請求后端的API接口,再加載出數據,這里的【某個合適的時間】是指:因為用戶查看網頁的時候並不會永遠都在切換頁面吧?所以在某個剛好的時間切換就行了
單頁面應用的原理
原理就是運用了錨點,即html頁面上的id屬性,因為id用的符號【#】,根據前面的web前端基礎開發,相信你已經可以理解了,比如一個頁面右邊的固定按鈕,返回頂部,比如這里淘寶的頁面,這個返回頂部的按鈕

用的就是【#】,這個就不多介紹了,因為學到vue這里,前面說過的,你得有錢端的基礎知識才更容易學。在js里【#】其實是hash值,比如這個例子:

因為js自帶有location對象,在我點擊登錄時,因為用onhashchange監聽了hash改變,所以立馬可以得到新的hash值,然后按邏輯把數據渲染出來
代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
</style>
</head>
<body>
<a href='#/login'>登錄</a>
<a href="#/register">注冊</a>
<div id="app">
</div>
<!-- <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> -->
<script>
var point = document.getElementById('app');
window.onhashchange = function () {
console.log(location);
switch (location.hash) {
case '#/login':
point.innerHTML = '<h2>登錄</h2>'
break;
case '#/register':
point.innerHTML = '<h2>注冊</h2>'
break;
default:
break;
}
}
</script>
</body>
</html>
總之在單頁面應用里,用【#】的意思是當前頁面根本就沒有跳轉,還是當前的頁面,只是用了一些機制把數據換掉了而已,這個機制就是vue-router,vue-router其實就是用了這個onhash的原理,不過比js原生的多了很多特性和功能
注:
- 錨點值即a標簽的跳轉,hash
- onhashchange獲取url上錨點的改變
- location.hash指當前的錨點
- js里也有switch的用法
vue-router
vue-router插件位置:

官方文檔傳送門:點我
vue-router簡介
這里說下,為什么要截圖官方的文檔,直接去官方文檔看不就好了嗎對吧,原因是:vue-router更新版本很快,所以文檔也會跟着更新,有些知識點可能有些不一樣。加上也就不用切換到另一個界面看了再回來看了,我截的圖也只是個人覺得需要注意的點

安裝vue-router

安裝之后當前目錄下多了個vue-router文件夾:

引入vue-router包
引入本地包
你可以引入你下載的本地的,真正的使用vue-router是和vue配套一起使用的,所以vue也得引入
引入cdn包

查看控制台如果沒報錯表示引入成功
引入cdn包代碼:
<script type="text/javascript" src='https://unpkg.com/vue-router/dist/vue-router.js'></script> <!-- 或者引入指定的版本 --> <script type="text/javascript" src='https://unpkg.com/vue-router@2.0.0/dist/vue-router.js'></script>
使用vue-router

使用步驟:
1.引入vue-router插件
2.讓根元素Vue載入自定義的VueRouter對象(此對象由vue-route插件提供,插件最后會返回一個VueRouter對象和router-linke和router-view組件),方面后面使用
3.創建、配置一個router對象,里面設定好不同的錨點值對應的路由以及對應好第二步里自定義的VueRoter對象
4.將創建好的router對象掛載到vue實例對象上,直接如上寫即可,如果報錯什么matched,一定是根元素Vue里沒有寫入router
5.利用vue-router插件提供的兩個全局的組件<router-link>和<router-view>設定好DOM布局,通過<router-link>組件的to屬性設定好路由路徑,且組件最后會被渲染成a標簽,<router-view>給定一個路由組件的出口,用於讓VueRouter對象進行數據渲染
6.根據不同的路由,渲染整個頁面,最后展示出來
注意:
當使用vue-router時,掛載組件只需要再VueRouter對象里掛載就行了,不需要再在vue實例對象里用components屬性掛載了
VueRouter定義路由組件的屬性是routes,不是router,定義的url屬性用path
定義的url路由不用手動寫上【#】,vue-router會自動添加上
以上就是vue-router的簡單使用
命名路由
vue的路由也可以命名的,是不是感覺越來越像一門后端語言了,哈哈

注:
使用命名路由,在定義路由組件內部,最好用v-bind綁定,添加一個name屬性,值則為你定義的路由名字,必須是字典形式:{name:'名字'}
我這里試了下,不用綁定直接使用也可以,以前的版本不行的,現在的貌似可以,具體還有待研究,我使用的版本:vue2.6.9,vue-router3.0.2

代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Vlogin = { template: `<div>登錄</div>` }
var Vregister = { template: `<div>注冊</div>` }
const router = new VueRouter({
routes: [{
path: '/login',
name:'login',
component: Vlogin },
{
path: '/register',
name:'register',
component: Vregister
}]
})
var Vcom = {
template: `<div>
<router-link :to="{name:'login'}">登錄頁面</router-link>
<router-link :to="{name:'register'}">注冊頁面</router-link>
<router-view></router-view></div>`
}
let app = new Vue({
el: '#app',
components: { Vcom },
router,
template: `<Vcom />`
})
</script>
</body>
</html>
默認路由
給默認的路由,因為很多時候打開頁面,總要展示一個默認的頁面吧,所以如下:給路由組件添加一個 '/',然后指向一個你覺得可以作為默認頁面的組件就行

補充一下,在vue-router3.0.1版本中,還有這種寫法:

但是由於我目前的是3.0.2,所有效果沒出來,並且我感覺沒多大用啊,反正都是渲染,直接用官方的就行了,搞些新寫法整那么花里胡哨干嘛對吧?
路由重定向
這個跟上面的默認路由很類似,只是用的是redirect屬性:
我這里訪問頁面會自動跳轉到登錄頁面,這種就是路由重定向

代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Vlogin = {
template: `<div>登錄</div>`
}
var Vregister = {
template: `<div>注冊</div>`
}
const router = new VueRouter({
routes: [{
path:'/',
redirect:'/login'
},
{
path: '/login',
component: Vlogin
},
{
path: '/register',
component: Vregister
}
]
})
var Vcom = {
template: `<div>
<router-link to="/login">登錄頁面</router-link>
<router-link to="/register">注冊頁面</router-link>
<router-view></router-view>
</div>`
}
let app = new Vue({
el: '#app',
components: {
Vcom
},
router,
template: `<Vcom />`
})
</script>
</body>
</html>
帶參數的路由
我們經常需要把某種模式匹配到的所有路由,全都映射到同個組件。例如,我們有一個 User 組件,對於所有 ID 各不相同的用戶,都要使用這個組件來渲染
帶參數是什么意思,比如就目前我這個博客園后台編輯頁面:

https://i.cnblogs.com/EditPosts.aspx?postid=10570774
其中,【?】后面的postid=10...就是帶的參數
除了這種,還有這種:

其中的p/105...就是參數,當然博客園的到底用的什么做的url路由就不得而知了,也與本文無關了。
總之就是這種:xxx/user/userid/1,其中的userid/1就是參數
總結下就是,有以下兩種參數,表達的意思都是一樣的,是為了找page等於多少的數據
xxx.com/cont?page=2
xxx.com/cont/page/1
那么在實際開發中,肯定會有指定某個參數的訪問,這種其實就是查詢嘛,查詢單個數據,也是非常常見且重要的,來個例子:
(有些圖片看着字很小或者又顯示不全,你右鍵查看圖片源地址可以看大圖的,這個是博客園主題的關系,顯示不全)

注意:
- 用【:】匹配的路由組件,path是這樣:/page/:pid,有【/】分割,在匹配時用的params,就可以匹配 /page/1,/page/2,/page/3等等的,瀏覽器url上顯示的是 /page/1
- 另一種匹配,路由組件中的path沒做任何改動,直接在匹配時用的query,就可以匹配 /page?pid=1,/page?pid=2,/page?pid=3等等的,瀏覽器url顯示的是 /page?pid=1
相關具體步驟:
1.重新定義了兩個局部組件,其中一個用 /page:pid ,為什么這么寫,這是官方文檔里明確說明了的:
2.再在router-link里多給了一個參數,params,在另外一個里添加了query:

params和query都是固定的,不能隨意更改,不信你可以改了試試。
<router-link :to="{name:'pagep',params:{pid:1}}">第一頁</router-link> 匹配對應前面的 xxx.com/cont/page/1<router-link :to="{name:'pageq',query:{pid:2}}">第二頁</router-link> 匹配對應前面的 xxx.com/cont?page=2
那有沒有想過,它這就給個參數(params/query),為什么就可以匹配呢?匹配之后可以拿到那個參數嗎?
你可以用this.$router和this.$route查看下 ,為什么是這兩個參數呢?因為讀源碼所得,當引入了vue-router之后,Vue實例化對象就多個兩個惡屬性,一個是$router,一個是$route

如下,給了一個已創建的生命周期函數,在生命周期里打印了this.$router,發現就是VueRouter對象,里面有相關的屬性

再打印this.$route看看,發現用【:】 可以匹配url的參數(比如這里用的 :pid),並且給這個參數加了個鍵,然后匹配到的參數會進入params參數里去,作為一個字典存在:

為什么要傳給params呢?你想想,像這樣的匹配,匹配到了之后,需要交給后端處理,那你怎么拿到這個參數並傳遞給后端呢?沒有變量名字你怎么傳?是不是需要一個形參啊?所以這里就有個params屬性,它對應一個字典,字典key就是定義路由組件時path部分,冒號后面的字段,值就是匹配到的值,比如這里就是:{pid:'1'}。
並且它還有個參數query,但是此時如上圖,query還是一個空字典。
也就是說這兩個屬性 query和params都是路由組件自帶的屬性,它本來就有的,所以知道為什么前面說在router-link綁定那里不能隨意換成其他參數了吧
關於這里,可能你理解起來有點吃力,如果你覺得比較吃力,得多看官方文檔,傳送門 多試幾個例子,我個人感覺它那官方文檔對於這里都沒說的多清楚
由於我是做Python開發的,因為Python的django框架里就有個路由匹配的參數 path('/page:int<pid>',func),其中的pid就可以類比成這里的pid,所以就很好理解,對這Python不熟悉的請忽略我說的Python這個部分
那么有了用【:】匹配,再看另一個url為/page?pid=2是否能拿到值呢?是否會把參數作為鍵值交給自己自帶的屬性query呢:
確實如此:

那假如說我把兩個router-link傳進的參數不小心寫錯了,本來是params的寫成query,本來是query寫成了params,看是否可以拿到呢:
拿是可以拿到,但是參數都進錯了歸屬,這種操作太非主流了,可以是可以,但不建議這么干

代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<style>
</style>
</head>
<body>
<body>
<div id="app">
</div>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Vpagep = {
template: `<div>第一頁內容</div>`,
created() {
console.log(this.$route)
},
}
var Vpageq = {
template: `<div>第二頁內容</div>`,
created() {
console.log(this.$route)
},
}
const router = new VueRouter({
routes: [{
path: '/page/:pid',
name: 'pagep',
component: Vpagep
},
{
path: '/page',
name: 'pageq',
component: Vpageq
}
]
})
var Vcom = {
template: `<div>
<router-link :to="{name:'pagep',query:{pid:1}}">第一頁</router-link>
<router-link :to="{name:'pageq',params:{pid:2}}">第二頁</router-link>
<router-view></router-view></div>`
}
let app = new Vue({
el: '#app',
components: {
Vcom
},
router,
template: `<Vcom />`
})
</script>
</body>
</html>
編程式導航
編程式導航,聽着那么高端大氣,到底什么是編程式導航呢,官方文檔解釋:

也就是說,編程式導航就是直接使用router實例的push方法,並且其實前面我們用的router-link組件最終其實也是用的這個push方法,換言之我們也可以直接使用這個push方法,自定義,自己編寫導航,這就是編程式導航
官網使用案例:
// 字符串 router.push('home') // 對象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: '123' }}) // 帶查詢參數,變成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }})
更多的就移步自己研究吧:點我
說了半天好像還是不夠深刻對吧?還是看例子:

看懂了吧?說白了就是,利用一個事件,在這個事件里把由router-link組件換成了$router.push(),傳進一個字典,字典和之前用的router-link傳入的一樣即可,這個字典就是name和params(或者是query)
push這個意思就很明顯了,就是把這些參數推進去
代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<style>
</style>
</head>
<body>
<body>
<div id="app">
</div>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Vpagep = {
template: `<div>第一頁內容</div>`,
created() {
console.log(this.$route)
},
}
var Vpageq = {
template: `<div>第二頁內容</div>`,
created() {
console.log(this.$route)
},
}
const router = new VueRouter({
routes: [{
path: '/page/:pid',
name: 'pagep',
component: Vpagep
},
{
path: '/page',
name: 'pageq',
component: Vpageq
}
]
})
var Vcom = {
template: `<div>
<button @click="firstHander">第一頁</button>
<button @click="secondHander">第二頁</button>
<router-view></router-view>
</div>`,
methods:{
firstHander(){
this.$router.push( {name:'pagep',params:{'pid':1}} )
},
secondHander(){
this.$router.push( {name:'pageq',query:{'pid':2}} )
}
}
}
let app = new Vue({
el: '#app',
components: {
Vcom
},
router,
template: `<Vcom />`
})
</script>
</body>
</html>
嵌套路由

因為路由組件之下,完全還有可能有細分的子路由組件之類的,這樣就可以把整個頁面切分成很多個模塊,每個模塊做着不同的分工,所以就需要有嵌套路由這個東西,
然后用法和路由組件是一樣的,就不用多說了,直接來個例子說明:
先看這個百度首頁,我圈出來的部分:

百度首頁和個人中心頁面當做路由的根組件,把我圈出來的部分作為子路由嵌套嵌套到個人中心路由組件里:

就是這么簡單,反正路由組件該有的都得有就行了
代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<style>
</style>
</head>
<body>
<body>
<div id="app">
</div>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Myfollow = {
template: `<div>我的關注</div>`
}
var Navigate = {
template: `<div>導航</div>`
}
var Story = {
template: `<div>小說</div>`
}
var Commend = {
tepmalte: `<div>推薦</div>`
}
var Person = {
template: `<div>個人主頁<br>
<router-link to="/Person/follow">我的關注</router-link>
<router-link to="/Person/navigate">導航</router-link>
<router-link to="/Person/story">小說</router-link>
<router-link to="/Person/commend">推薦</router-link>
<router-view></router-view></div>`
}
var Home = {
tempalte: `<div>百度首頁</div>`
}
const router = new VueRouter({
routes: [{
path: '/Person',
component: Person,
children: [{
path: '/Person/follow',
component: Myfollow
},
{
path: '/Person/story',
component: Story
},
{
path: '/Person/commend',
component: Commend
},
{
path: '/Person/navigate',
component: Navigate
},
]
},
{
path: '/home',
component: Home
}
]
})
var Root = {
template: `<div>
<router-link to="/home">百度首頁</router-link>
<router-link to="/Person">個人主頁</router-link>
<router-view></router-view></div>`
}
const app = new Vue({
el: '#app',
router,
components: {
Root,
},
template: `<Root />`,
})
</script>
</body>
</html>
子路由的path
唯一要注意的是,寫子路由的path時,要嘛帶上完整的路由:

要嘛不要帶/,直接給一個路由的相對路徑,vue會自動拼寫成完整路由,其他沒做任何改變,一樣可以顯示:

動態路由

我畫出來的那個【'$route'】這個要注意,后面我們會用到
什么是動態路由呢,我個人覺得官網講的太隨意了, 你看了估計都看不太懂啥意思
那么動態路由到底是什么呢?這么說吧,因為Vue是單頁面應用,那么就會有很多公用路由組件部分對吧,那么這些公用組件部分會被多個組件使用,通常的方法就是把公用路由組件掛載成子組件,然后公用的部分顯示,不同的部分做單獨渲染或者說單獨的覆蓋數據就行。
這意思感覺有點像是模板一樣對吧?反正都是那一套模板,把數據放進去就行了,好的,不多說,直接上例子:
先看個網站,稀土掘金的,這個也是個開發者社區,然后我標記出來的,1就是根路由,2就是子路由,3就是公用部分(這個是要賬號登錄狀態才有的),不管我點2部分的路由的哪個標簽,3永遠都有的,而且沒有變,切換的永遠是3下面的數據,並且3下面的數據的css樣式也是公用部分:

好的,簡單的模仿一個:
(為了在一個頁面顯示,所以排版看着有點怪)

看下控制台打印的結果:

大概什么邏輯呢?就是相同部分都用同一個路由組件作為子組件,在父級路由的router-link里傳入對應的標簽參數,在公用路由組件里做下處理,把內容填充上就行,不再需要分別定義多個組件了。
這個在實際開發中,可以再公用路由組件里做判斷,如果是哪個子路由,數據就是什么樣,做好不同的分類顯示就行了,這里作為案例就沒做那么詳細真實了
好的,至於這個 '$route'(to,form) 其中的'$route'到底是什么暫且不 談了,詳細的看官網了
代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<style>
</style>
</head>
<body>
<body>
<div id="app"></div>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var Pins = {
template: ` <div>我是沸點</div>`
}
var common = { // 公用組件
data() {
return {
msg: ''
}
},
template: `<div>公用部分:發表 - 寫文章 - 分享鏈接
<div>{{msg}}</div></div>`,
created() {
this.msg = '(css樣式結構,還沒有數據)'
},
watch: {
'$route'(to, form) {
console.log(form);
console.log(to);
this.msg = `${this.$route.params.category} 相關內容內容內容.........`
}
}
}
var home = {
template: `<div>
<router-link :to="{name:'common',params:{category:'commend'}}">推薦</router-link>
<router-link :to="{name:'common',params:{category:'follow'}}">關注</router-link>
<router-link :to="{name:'common',params:{category:'android'}}">安卓</router-link>
<router-view></router-view></div>`,
}
// 注意路由掛載組件的先后順序,先創建再在路由里掛載
const router = new VueRouter({
routes: [{
path: '/home',
component: home,
children: [{
path: '/',
component: common
},
{
path: '/home/:category',
name: 'common',
component: common
}
]
},
{
path: '/pins',
name: 'pins',
component: Pins
}
]
})
var com = {
template: `<div>
<router-link to="/home">首頁</router-link>
<router-link to="/pins">沸點</router-link>
<router-view></router-view></div>`
}
const app = new Vue({
el: '#app',
components: {
com
},
router,
template: `<com/>`
})
</script>
</body>
</html>
keep-alive的用法
在路由組件中也可以用keep-alive,主要用途是對切換頁面時組件的緩存,防止銷毀創建增大開銷
這個在前面的局部組件也有用到的,不多說。用法就是在組件的出口前后加一個vue特殊的組件<keep-alive>包裹住即可
其他沒變只是在入口函數那里加了keep-alive組件

全局前置守衛驗證
這個全局前置守衛在舊版的vue-router里名字叫全局守衛
在開發中,按照常識,都知道,不同用戶的權限是不一樣的,然后能訪問的路由也是不一樣的,所以這就是權限,而作為權限驗證,得有一套機制吧,這套機制就是全局守衛
比如,某個網站,驗證用戶的登錄狀態,如果未登錄就提示登陸,否則就進不了需要登錄的網頁,必須登錄之后才可以查看網頁,這種場景就可以用全局前置守衛
相關的說明:


上面這個說的什么意思呢,主要就是說,必須要調用next方法,不然的話會卡住
路由元信息
首先呢,路由組件有一個元信息meta參數,這個參數就可以配置一些權限驗證:

這里給一個小demo,如下,這是優酷視頻網的某個部分,上面是免費視頻,下面是需要會員才能看的視頻

好的,就做個這種簡單的出來:

點擊會員時,它會自動跳轉到登錄頁面


當我登錄之后,會員頁面顯示:

以上部分,在router-link傳入參數部分,可能有朋友會想,唉,你這為什么要定義兩個公用組件,都那一套啊,免費電影和會員部分都用一套公用組件多省事啊,確實啊,這樣確實省事,其實最開始我就是這樣的,但是因為都用一個公用組件,在不同根組件切換到子組件時,會有錯亂,達不到我們的需要的效果,所以我定義了兩個公用組件。並且針對兩個組件,后期肯定還會有不同的配置的,所以這樣會更好維護一點
原理就是在定義路由時,給需要驗證的路由配置原信息,加了個meta參數,這個參數是router對象自帶的屬性,我們可以隨意定義鍵值進去:

利用這個鍵值用beforeEach全局守衛在路由跳轉時判斷這個參數,如果為true則需要做驗證,驗證通過則next()為空放行,驗證不通過則用next跳轉,這里的next是個回調函數,有點編程式導航router.push的意思,此時這個beforeEach全局守衛其實也可以看出一個周期鈎子函數

對於驗證登錄狀態,用了js自帶的一個localStorage永久存儲對象作為存儲 :

需要清除的話,右鍵那個那個file://,點clear就行,詳細的就不多說了,自行查資料研究吧
完整代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script>
<style>
.common{
margin-top: 2%;
width: 60%;
height: 100px;
background: purple;
color: white;
border: 1px solid rgb(144, 143, 143);
text-align: center;
line-height: 50px;
}
.mcommon{
margin-top: 2%;
width: 60%;
height: 100px;
background-color: rgb(9, 78, 108);
color:white;
border: 1px solid rgb(172, 168, 168);
text-align: center;
line-height: 50px;
}
</style>
</head>
<body>
<body>
<div id="app"></div>
<script>
Vue.use(VueRouter) // 目前是全局狀態,可有可不有
var login = {
data() {
return {
name: '',
pwd: ''
}
},
template: `<div>
<input type='text' v-model="name">
<input type='password' v-model='pwd'>
<button @click="loginHander" >登錄</button>
</div>`,
methods: {
loginHander() {
localStorage.setItem('user', {
'name': this.name,
'pwd': this.pwd
})
this.$router.push({
path: '/member'
})
}
},
}
var common = { // 免費電影公用組件
data() {
return {
msg: ''
}
},
template: `<div class="common">免費電影公用部分:XXXXX
<div>{{msg}}</div></div>`,
created() {
this.msg = '(css樣式結構,還沒有數據)'
},
watch: {
'$route'(to, form) {
console.log(form);
console.log(to);
this.msg = `${this.$route.params.category} 相關內容內容內容.........`
}
}
}
var mcommon = { // 會員電影公用組件
data() {
return {
msg: ''
}
},
template: `<div class="mcommon">會員電影公用部分:XXXXX
<div>{{msg}}</div></div>`,
created() {
this.msg = '(css樣式結構,還沒有數據)'
},
watch: {
'$route'(to, form) {
console.log(form);
console.log(to);
this.msg = `${this.$route.params.category} 相關內容內容內容.........`
}
}
}
var movie = { // 免費視頻
template: `<div>
<router-link :to="{name:'common',params:{category:'hollywood'}}">好萊塢</router-link>
<router-link :to="{name:'common',params:{category:'trailer'}}">預告片</router-link>
<router-link :to="{name:'common',params:{category:'online-movie'}}">網絡電影</router-link>
<router-view></router-view></div>`,
}
var member = { // 會員視頻
template: `<div>
<router-link :to="{name:'mcommon',params:{category:'lastest'}}">最新</router-link>
<router-link :to="{name:'mcommon',params:{category:'cinema'}}">院線大片</router-link>
<router-link :to="{name:'mcommon',params:{category:'exclusive'}}">獨播強擋</router-link>
<router-link :to="{name:'mcommon',params:{category:'popluar'}}">熱門紀實</router-link>
<router-link :to="{name:'mcommon',params:{category:'bbc'}}">BBC經典</router-link>
<router-link :to="{name:'mcommon',params:{category:'anime'}}">熱血動漫</router-link>
<router-view></router-view></div>`,
};
// 注意路由掛載組件的先后順序,先創建再在路由里掛載
const router = new VueRouter({
routes: [{
path: '/movie',
component: movie,
children: [{
path: '/',
component: common
},
{
path: '/movie/:category',
name: 'common',
component: common
}
]
},
{
path: '/member',
component: member,
meta: { // 帶有該參數,表示需要認證
auth: true
},
children: [
// 有認證之后不能再加默認路由,因為加了默認路由之后自動跳到根目錄,使認證失效
// {
// path: '/',
// component: mcommon
// },
{
path: '/member/:category',
name: 'mcommon',
component: mcommon
}
]
},
{
path: '/login',
component: login,
name: 'login'
}
]
})
router.beforeEach((to, from, next) => {
// to and from are both route objects. must call `next`.
console.log(from);
console.log(to.meta.auth);
if (to.meta.auth) {
if (localStorage.getItem('user')) {
next()
} else {
next({
path: '/login'
})
}
} else {
next()
}
})
var com = {
template: `<div>
<router-link to="/movie">電影</router-link>
<router-link to="/member">會員</router-link>
<router-link to="/login">登錄</router-link>
<keep-alive>
<router-view></router-view>
</keep-alive></div>`
}
const app = new Vue({
el: '#app',
components: {
com
},
router,
template: `<com/>`
})
</script>
</body>
</html>
官方文檔里其實還有一個路由內部的守衛是這個:beforeEnter,這個就自己研究了

在vue-router的官方文檔里,守衛一共有這么多,自己研究了

補充
如果你遇到這樣的報錯:

檢查你的組件,看template參數寫對沒有
如果遇到路由匹配到了,但是url沒有正常顯示:
路由組件如下,

編程式導航部分:

coursedetail部分:

頁面顯示:

這樣雖然有顯示,但是url不對,原因是參數匹配有誤,路由組件用的參數名是courseId,在做編程式導航時用的參數是detailId,我上面已經標注出來了
作如下改動,即可:


頁面正常顯示:

總結:
vue-router就到這里,我把經常用到的知識點都揉在一起了,篇幅有點長,耐心看吧,其實都挺簡單的,只是有些地方稍微注意一下就行
