前端路由 看到這裡可能有朋友有疑惑了,前端也有路由嗎?這些難道不應該是在後端部分操作的嗎?確實是這樣,但是現在前後端分離後,加上現在的前端框架的實用性,為的就是均衡前後端的工作量,所以在前端也有了路由,減輕了伺服器對這方面的判斷,在前端做好路由分發之後,後端就只需要寫API介面了,更著重於數據... ...
前端路由
看到這裡可能有朋友有疑惑了,前端也有路由嗎?這些難道不應該是在後端部分操作的嗎?確實是這樣,但是現在前後端分離後,加上現在的前端框架的實用性,為的就是均衡前後端的工作量,所以在前端也有了路由,減輕了伺服器對這方面的判斷,在前端做好路由分發之後,後端就只需要寫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>原生js的路由控制
總之在單頁面應用里,用【#】的意思是當前頁面根本就沒有跳轉,還是當前的頁面,只是用了一些機制把數據換掉了而已,這個機制就是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/[email protected]/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-router 命名路由
預設路由
給預設的路由,因為很多時候打開頁面,總要展示一個預設的頁面吧,所以如下:給路由組件添加一個 '/',然後指向一個你覺得可以作為預設頁面的組件就行
補充一下,在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>router-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 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: [ // 有認證之後不能再加預設路