Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面 SPA(Single Page Application)應用變得易如反掌。
什么是路由?
請看下面這個例子:通過 ajax 請求,更新頁面局部內容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <a href="#/login">登錄頁面</a> <a href="#/register">注冊頁面</a> <div id="app"> </div> <script type="text/javascript"> var oDiv = document.getElementById('app'); window.onhashchange = function() { console.log(location.hash); switch (location.hash) { case '#/login': oDiv.innerHTML = '<h2>我是登錄頁面</h2>' break; case '#/register': oDiv.innerHTML = '<h2>我是注冊頁面</h2>' break; default: // statements_def break; } } </script> </body> </html>
那 Vue Router 能干什么?
它能使獲取請求更新頁面的過程更可配置,也就是簡化上面的代碼,提供更豐富的配置
看下面這個例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"></div> <!-- 1.引入vue.js --> <script type="text/javascript" src="../js/vue.min.js"></script> <!-- 2.引入核心的插件vue-router --> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> // 2.讓vue使用該VueRouter創建 Vue.use(VueRouter); //聲明組件 var Login = { template: `<div>我是登錄頁面</div>` }; var Register = { template: `<div>我是注冊頁面</div>` }; // 3.創建路由對象 var router = new VueRouter({ // 4.配置路由對象 routes: [ // 路由匹配的規則 { path: '/login', component: Login }, { path: '/register', component: Register } ] }); // 4.使用兩個全局的組件 router-link router-view var App = { template: ` <div> <!--router-link默認會被渲染成a標簽,to默認會被渲染成href屬性--> <router-link to = '/login'>登錄</router-link> <router-link to = '/register'>注冊</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` } // Cannot read property 'matched' of undefined // 5.將配置好的路由對象關聯到vue實例化對象中 new Vue({ el: '#app', router: router, template: `<App />`, components: { App } }); </script> </body> </html>
如果 path 非常長的話,可以給路由的匹配規則起個別名,代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"></div> <!-- 1.引入vue.js --> <script type="text/javascript" src="../js/vue.min.js"></script> <!-- 2.引入核心的插件vue-router --> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> // 2.讓vue使用該VueRouter創建 如果vue是一個局部作用域的對象 那么必須Vue.use(VueRouter); // Vue.use(VueRouter); //聲明組件 var Login = { template: `<div>我是登錄頁面</div>` }; var Register = { template: `<div>我是注冊頁面</div>` }; // 3.創建路由對象 var router = new VueRouter({ // 4.配置路由對象 routes: [ // 路由匹配的規則 { path: '/login', name: 'login', component: Login }, { path: '/register', name: 'register', component: Register } ] }); // 4.拋出兩個全局的組件 router-link router-view var App = { template: ` <div> <!--router-link默認會被渲染成a標簽,to默認會被渲染成href屬性--> <router-link :to = "{name:'login'}">登錄</router-link> <router-link :to = "{name:'register'}">注冊</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` } // Cannot read property 'matched' of undefined // 5.將配置好的路由對象關聯到vue實例化對象中 new Vue({ el: '#app', router: router, template: `<App />`, components: { App } }); </script> </body> </html>
可以給路由綁定參數
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"></div> <!-- 1.先引入vue.js --> <script type="text/javascript" src="../js/vue.min.js"></script> <!-- 2.引入核心的插件vue-router --> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> // 地址欄 路由范式 //(1)xxxxx.html#/user/1 params 動態路由參數 //(2)ooooo.html#/user?userId = 1 query // Vue.use(VueRouter); //聲明組件 $router $route (路由信息對象) var UserParams = { template: `<div>我是用戶1</div>`, created() { console.log(this.$router); console.log(this.$route); } }; var UserQuery = { template: `<div>我是用戶2</div>`, created() { console.log(this.$route); } }; // 3.創建路由對象 var router = new VueRouter({ // 4.配置路由對象 routes: [ // 路由匹配的規則 { //動態路由參數 以冒號開頭 path: '/user/:id', name: 'userP', component: UserParams }, { path: '/user', name: 'userQ', component: UserQuery } ] }); // 使用兩個全局的組件 router-link router-view var App = { template: ` <div> <!--router-link默認會被渲染成a標簽,to默認會被渲染成href屬性--> <router-link :to = "{name:'userP',params:{id:1}}">用戶1</router-link> <router-link :to = "{name:'userQ',query:{userId:2}}">用戶2</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` } // Cannot read property 'matched' of undefined // 5.將配置好的路由對象關聯到vue實例化對象中 new Vue({ el: '#app', router: router, template: `<App />`, components: { App } }); </script> </body> </html>
路由也可以嵌套使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"></div> <!-- 1.先引入vue.js --> <script type="text/javascript" src="../js/vue.min.js"></script> <!-- 2.引入核心的插件vue-router --> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> // 地址欄 路由范式 //(1)xxxxx.html#/user/1 params 動態路由參數 //(2)ooooo.html#/user?userId = 1 query // Vue.use(VueRouter); //聲明組件 var Song = { template: `<div>我是歌曲組件</div>`, created() { console.log(this.$router); console.log(this.$route); } }; var Movie = { template: `<div>電影組件</div>`, created() { console.log(this.$route); } }; // 3.創建路由對象 // /home/song // /home/movie var Home = { template: ` <div> 首頁內容 <br /> <router-link to = '/home/song'>歌曲</router-link> <router-link to = '/home/movie'>電影</router-link> <router-view></router-view> </div> ` }; var router = new VueRouter({ // 4.配置路由對象 routes: [ // 路由匹配的規則 { //動態路由參數 以冒號開頭 path: '/home', name: 'home', component: Home, children: [{ path: 'song', component: Song }, { path: 'movie', component: Movie }, ] } ] }); // 使用兩個全局的組件 router-link router-view var App = { template: ` <div> <!--router-link默認會被渲染成a標簽,to默認會被渲染成href屬性--> <router-link :to = "{name:'home'}">首頁</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` } // Cannot read property 'matched' of undefined // 5.將配置好的路由對象關聯到vue實例化對象中 new Vue({ el: '#app', router: router, template: `<App />`, components: { App } }); </script> </body> </html>
動態路由匹配(地址欄中參數的變化和watch的使用)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"></div> <!-- 1.先引入vue.js --> <script type="text/javascript" src="../js/vue.min.js"></script> <!-- 2.引入核心的插件vue-router --> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> // 地址欄 路由范式 //(1)xxxxx.html#/user/1 params 動態路由參數 //(2)ooooo.html#/user?userId = 1 query // Vue.use(VueRouter); var ComDesc = { data() { return { msg: '' } }, template: ` <div> {{ msg }} </div> `, created() { this.msg = 'andorid'; console.log(1); }, watch: { '$route'(to, from) { // 對路由變化作出響應... console.log(to); console.log(from); this.msg = to.params.id; } } } // 3.創建路由對象 // /timeline/andorid // /timeline/frontend var Timeline = { template: ` <div id = 'timeline'> <router-link :to ="{name:'comDesc',params:{id:'andorid'}}" >安卓</router-link> <router-link :to ="{name:'comDesc',params:{id:'frontend'}}">前端</router-link> <router-view></router-view> </div> ` }; var Pins = { template: ` <div>我是沸點</div> ` } var router = new VueRouter({ // 4.配置路由對象 routes: [ // 路由匹配的規則 { //動態路由參數 以冒號開頭 path: '/timeline', name: 'timeline', component: Timeline, children: [{ name: 'comDesc', path: '/timeline/:id', component: ComDesc } ] }, { path: '/pins', component: Pins } ] }); // 使用兩個全局的組件 router-link router-view var App = { template: ` <div> <!--router-link默認會被渲染成a標簽,to默認會被渲染成href屬性--> <router-link to = '/timeline'>首頁</router-link> <router-link to = '/pins'>沸點</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` } // Cannot read property 'matched' of undefined // 5.將配置好的路由對象關聯到vue實例化對象中 new Vue({ el: '#app', router: router, template: `<App />`, components: { App } }); </script> </body> </html>
meta和全局路由的渲染前配置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <!-- 聲明式的導航 --> <router-link to='/home'>首頁</router-link> <router-link to='/blog'>我的博客</router-link> <router-link to='/login'>登錄</router-link> <a href="javascript:void(0);" @click='clear'>退出</a> <router-view></router-view> </div> <script type="text/javascript" src="../js/vue.min.js"></script> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> Vue.use(VueRouter); var Home = { template: ` <div> 我是首頁 </div> ` }; var Blog = { template: ` <div> 我是博客 </div> ` }; var Login = { data() { return { name: '', pwd: '' } }, template: ` <div> <input type="text" v-model ='name'/> <input type="text" v-mode = 'pwd'/> <input type="button" value ='登錄' @click = 'login'/> </div> `, methods: { login() { localStorage.setItem('user', { name: this.name, pwd: this.pwd }); // 編程式導航 this.$router.push({ name: 'blog' }); } } }; var router = new VueRouter({ routes: [{ path: '/', redirect: '/home' }, { path: '/home', component: Home }, { name: 'blog', path: '/blog', component: Blog, // 給未來路由 做權限控制 全局路由守衛 來做參照條件 meta: { // 表明用戶訪問該組件是需要登錄,auth是自定義的參數 auth: true } }, { path: '/login', component: Login } ] }); router.beforeEach((to, from, next) => { console.log(to); console.log(from); if (to.meta.auth) { //用戶點擊了博客鏈接 該用戶未登錄 需要登錄判斷 准備跳轉登錄頁面 if (localStorage.getItem('user')) { // alert(1); // 不為空 放行 next(); } else { // alert(2); // 用戶需要登錄 next({ path: '/login' }); } } else { // 直接放行 next(); //如果不調用next 就會卡住 } }); new Vue({ el: '#app', router, methods: { clear() { localStorage.removeItem('user'); this.$router.push('/login'); } } }); </script> </body> </html>
keep-alive在路由中的使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> </div> <script type="text/javascript" src="../js/vue.min.js"></script> <script type="text/javascript" src="../js/node_modules/vue-router/dist/vue-router.min.js"></script> <script type="text/javascript"> Vue.use(VueRouter); var Series = { template: ` <div>付費欄目</div> `, created() { console.log('付費欄目組件created'); }, mounted() { console.log('付費欄目組件mounted'); }, destroyed() { console.log('付費欄目組件被銷毀了') } }; var Topics = { template: ` <div> <h3 @click = 'clickHandler'>我是專題廣場</h3> </div> `, methods: { clickHandler(e) { e.target.style.color = 'red'; } }, created() { console.log('專題廣場組件created'); }, mounted() { console.log('專題廣場組件mounted'); }, destroyed() { console.log('專題廣場組件被銷毀了') } }; var router = new VueRouter({ routes: [{ path: '/series', component: Series }, { path: '/topics', component: Topics }, ] }); var App = { template: ` <div> <router-link to = '/series'>付費欄目</router-link> <router-link to = '/topics'>專題廣場</router-link> <keep-alive> <router-view></router-view> </keep-alive> </div> ` } new Vue({ el: '#app', template: `<App />`, components: { App }, router }); </script> </body> </html>
