前端路由的實現原理
為什么要做單頁面應用?
- (1) 傳統的開發方式url改變后,立馬發送請求響應整個頁面, 有可能資源過多,傳統開發會讓前端的頁面出現"白屏", 用戶體驗較差
- (2) SPA單頁面應用:錨點值的改變后不會立刻發送請求, 而是在某個合適的時機, 發送ajax請求, 局部改變頁面中的數據, 頁面不立刻跳轉
前端路由
- 1 錨點值監視
- 2 ajax獲取動態的數據
- 3 核心點是錨點值的改變
如何使用vue-router
下載 vue-router
npm init --yes
npm install vue-router --save
1 引入vue-router模塊 默認會拋出一個VueRouter對象 另外還有兩個全局的組件 router-link, router-view
<script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/vue-router.js"></script>
2 使用VueRouter
Vue.use(VueRouter);
3 創建路由對象
// 創建一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ { path:'/login', component:Login }, { path:'/register', component:Register } ] });
4 路由對象掛載到vue實例化對象中
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> ` }; new Vue({ el:'#app', components:{ App }, //掛載 router, template:`<App />` });
使用實例:
<div id="app"></div> <script type="text/javascript" src="node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script> // 讓vue使用VueRouter創建 Vue.use(VueRouter); var Login = { template: ` <div>登錄頁面</div> ` }; var Register = { template: ` <div>注冊頁面</div> `, } // 創建一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ { path:'/login', component:Login }, { path:'/register', component:Register } ] }); var App = { // router-link默認會被渲染成a標簽 to屬性默認會被渲染成href屬性 template: ` <div> <router-link to="/login">登錄頁面</router-link> <router-link to="/register">注冊頁面</router-link> <!--路由組件的出口--> <router-view></router-view> </div> ` }; new Vue({ el: '#app', components: { App }, router, template: `<App/>` })
5 命名路由
給當前的配置路由信息對象設置name:'login'屬性 :to = "{name:'login'}" <router-link :to="{name:'login'}">登陸</router-link> <router-link :to="{name:'register'}">注冊</router-link> var router = new VueRouter({ routes:[ { path:'/login', name:'login', component: Login }, { path:"/register", name:"register", component:Register } ] });
6 路由規范
(1) xxxx.html#/user/1
//配置路由對象 var userParam = { template:"<div>用戶1</div>", created(){ console.log(this.$router); console.log(this.$route); console.log(this.$route.params.user_id) } }; { path:'/user/:id', component:User } <router-link :to = "{name:'user',params:{id:1}}"></router-link>
(2) xxxx.html#/user?userId = 1
var userQuery = { template:"<div>用戶2</div>", created(){ console.log(this.$router); console.log(this.$route); console.log(this.$route.query.user_id) } }; { path:'/user' } <router-link :to = "{name:'user',query:{id:1}}"></router-link> //在組件內部通過this.$route 獲取路由信息對象
7 嵌套路由
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的對象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter對象 vue-router 還給咱們提供了兩個全局的組件 router-link router-view--> <script type="text/javascript"> // 嵌套路由: // 需求:進入首頁之后 點擊音樂/hone/music 電影 /home/movie Vue.use(VueRouter); var Home = { template:` <div> <br/> <router-link to="/home/music">音樂</router-link> <router-link to="/home/moive">電影</router-link> <! --子路由組件--> <router-view></router-view> </div> `, }; var Music = { template:` <div> 我是音樂</div> ` }; var Moive = { template:` <div> 我是電影</div> ` }; // 3.創建一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ { // 根目錄默認跳轉到home path:'/', redirect:'/home' // redirect:{name:'home'} }, { path: '/home', name:'home', component:Home, children:[ // 動態路由匹配表示自組件中的結構是不同的 // 當訪問/home時, Home組件的出口是不會渲染任何內容, 這是因為沒有匹配到合適的子路由 { path:'', component:Music }, { path:'music', component:Music }, { path:'moive', component:Moive } ] } ] }); var App = { template:` <div> <router-link :to="{name:'home'}">首頁</router-link> <router-view></router-view> </div> `, }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script> </body> </html>
8 動態路由匹配
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的對象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter對象 vue-router 還給咱們提供了兩個全局的組件 router-link router-view--> <script type="text/javascript"> Vue.use(VueRouter); var Timeline = { template:` <div> <router-link :to="{name:'comDesc', params:{id:'安卓'}}">安卓</router-link> <router-link :to="{name:'comDesc', params:{id:'前端'}}">前端</router-link> <router-link :to="{name:'comDesc', params:{id:'python'}}">python</router-link> <router-link :to="{name:'comDesc', params:{id:'JAVA'}}">JAVA</router-link> <router-view></router-view> </div> `, }; var Pins = { template:` <div> 我是沸點</div> ` }; // 共同的子組件 var ComDesc = { data(){ return { msg:'' } }, template:` <div> 我是一個{{msg}} </div> `, created(){ this.msg = '安卓' }, watch:{ '$route'(to, from){ console.log(to); console.log(from); this.msg = to.params.id } } }; // 3.創建一個路由對象 var router = new VueRouter({ // 配置路由對象 routes:[ // 動態的路由參數以冒號開頭 { path: '/timeline', name: 'timeline', component: Timeline, children:[ { path: "", component:ComDesc }, { path:"/timeline/:id", name:'comDesc', component:ComDesc } ] }, { path: '/pins', name: 'pins', component: Pins } ] }); var App = { template:` <div> <router-link to = "/timeline">首頁</router-link> <router-link to = "/pins">沸點</router-link> <!--路由組件的出口--> <router-view></router-view> </div> `, }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script>
9 keep-alive在路由中的使用
保持組件之前的狀態
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/vue-router.js"></script> <script> Vue.use(VueRouter); var home = { template: `<div> 我是首頁 </div>` }; var Pins = { template: ` <div> <h3 @click='clickHandler'>我是沸點</h3> </div> `, created(){ console.log("沸點組件創建了") }, mounted(){ console.log("沸點組件DOM加載了") }, destroyed(){ console.log("沸點銷毀了") }, methods:{ clickHandler(e){ e.target.style.color = 'red'; } } }; var router = new VueRouter({ routes: [ { path: '/home', component: home, }, { path: "/pins", name: "pins", component: Pins } ] }); var App = { template: `<div> <router-link to="/home">首頁</router-link> <router-link to="/pins">沸點</router-link> <keep-alive> <router-view></router-view> </keep-alive> </div>` }; new Vue({ el: '#app', router, template: `<App/>`, components:{App} }) </script> </body> </html>
10 權限控制
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的對象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter對象 vue-router 還給咱們提供了兩個全局的組件 router-link router-view--> <script type="text/javascript"> Vue.use(VueRouter); // 導航欄上 有首頁 智能題庫 登錄退出 四個按鈕 // 用戶訪問首頁時 看到的是首頁的內容 // 1.當用戶訪問智能題庫時,此時我們檢測用戶是否有權限訪問該智能題庫的內容, // 如果沒有 檢測用戶是否登錄過,如果沒有,則跳轉登錄頁面,登錄完成之后。 // 在localStroage中通存儲該用戶的用戶名和密碼,並且立刻跳轉到智能題庫頁面 // 2.當用戶點擊黜退,該用戶直接刪除 var Home = { template:` <div> 我是首頁 <router-view></router-view> </div> ` }; var Questionbank = { template:` <div> 我是題庫 <router-view></router-view> </div> ` }; var Login ={ data(){ return{ name:'', pwd:'' } }, template:` <div> <input type="text" v-model = 'name'/> <input type="text" v-model = 'pwd'/> <input type="submit" value="登錄" @click = 'loginHandler'/> </div> `, methods:{ loginHandler(){ // 要登錄了 // 存儲用戶名和密碼保存到locaStorage 然后跳轉相應的路由 localStorage.setItem('user', {name: this.name, pwd: this.pwd}); // 編程式導航 this.$router.push({name:'questionbank'}) } } } var router = new VueRouter({ // 配置路由對象 routes:[ // 動態的路由參數以冒號開頭 { path: '/home', name: 'home', component: Home }, { path: '/questionbank', name: 'questionbank', component: Questionbank, // 給未來的路由做權限控制 meta:{ // 如果是true表明該組件需要登錄 auth:true } }, { path:'/login', component:Login } ] }); // 全局的導航守衛 router.beforeEach(function (to, from, next) { console.log(to); console.log(from); if(to.meta.auth){ // 用戶點擊了智能題庫導航 該用戶未登錄, 需要登錄判斷 if(localStorage.getItem('user')){ // 不為空 放行 next() }else { // 為空 進行登錄頁面 next({path:'/login'}) } }else { // 如果不調用next那么頁面會卡住 // 直接放行 next(); } }); var App = { template:` <div> <router-link to = "/home">首頁</router-link> <router-link to = "/questionbank">智能題庫</router-link> <router-link to = "/login">登錄</router-link> <a href="javascripy:void(0)" @click ='clear'>退出</a> <!--路由組件的出口--> <keep-alive> <router-view></router-view> </keep-alive> </div> `, methods:{ clear(){ // 退出 localStorage.removeItem('user'); this.$router.push('/log') } } }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script> </body>