您好,登錄后才能下訂單哦!
今天來(lái)談?wù)剉ue項(xiàng)目{vue,vue-router,component
}三大神將之一的vue-router。作為我們前后端分離很重要的實(shí)踐之一,router幫我們完成了SPA應(yīng)用間的頁(yè)面跳轉(zhuǎn)。
并且,配合axios這樣的第三方庫(kù),我們可以實(shí)現(xiàn)配合后臺(tái)接口的攔截器功能。
對(duì)于一個(gè)小型項(xiàng)目而言,router這個(gè)文件夾里面就包含了一個(gè)router.js就足夠了,
但是,當(dāng)我們的頁(yè)面比較多的時(shí)候,我們就需要分出兩個(gè)文件出來(lái):一個(gè)定義我們的路由和組件,另一個(gè)實(shí)例化組件,并將路由掛載到vue的實(shí)例上。
基本的用法就不多贅述,大家可以看vue-router的官網(wǎng),認(rèn)真過(guò)一遍的話,基本使用肯定沒(méi)什么問(wèn)題。
1.為什么我的路由不起作用?
這里有個(gè)非常重要的一點(diǎn)就是當(dāng)我們?nèi)?gòu)造VueRouter的實(shí)例的時(shí)候,傳入的參數(shù)的問(wèn)題。
import routes from '@/router/router' const router = new VueRouter({ routes // (ES6語(yǔ)法)相當(dāng)于 routes: routes }) new Vue({ router }).$mount('#app')
如果你這里引入的不是routes,你就要按照下面的方式來(lái)寫(xiě)。
import vRoutes from '@/router/router' const router = new VueRouter({ routes :vRoutes }) new Vue({ router }).$mount('#app')
2.在路由中基于webpack實(shí)現(xiàn)組件的懶加載
對(duì)于我們的vue項(xiàng)目,我們基本都是運(yùn)用webpack打包的,如果沒(méi)有懶加載,打包后的文件將會(huì)異常的大,造成首頁(yè)白屏,延時(shí)嚴(yán)重,不利于用戶體驗(yàn),而運(yùn)用懶加載則可以將頁(yè)面進(jìn)行劃分,webpack將不同組件打包成很多個(gè)小的js文件。需要的時(shí)候再異步加載,優(yōu)化用戶的體驗(yàn),換而言之,有的頁(yè)面可能100個(gè)用戶只有一兩個(gè)會(huì)進(jìn)去,何必把流量花在它身上。
import App from '@/App.vue' const index = r => require.ensure([], () => r(require('@/pages/index/index')), 'index') export default [{ path: '/', component: App, children: [ { path: '/index', name:'index', component: index }] }]
如果某個(gè)組件包含了嵌套路由,我們也可以將兩個(gè)路由打包到一個(gè)js chunk中。
// 這兩條路由被打包在相同的塊中,訪問(wèn)任一路由都會(huì)延遲加載該路由組件 const orderUser= r => require.ensure([], () => r(require('@/pages/order/user')), 'order') const payRecord= r => require.ensure([], () => r(require('@/pages/order/payRecord')), 'order')
3.router的模式
對(duì)于瀏覽器,我們的router分為兩種模式。
1.hash模式(默認(rèn))
按照一個(gè)uri的基本結(jié)構(gòu)來(lái)說(shuō),hash模式就是在一個(gè)基本的URI的片段進(jìn)行的處理。如果拋開(kāi)SPA的話,比較常見(jiàn)的應(yīng)用場(chǎng)景就是我們?cè)谧鰌c商城的時(shí)候,會(huì)有比如說(shuō):商品詳情,評(píng)論,商品參數(shù)這樣的tab切換,就可以使用a標(biāo)簽配合id使用,加上一點(diǎn)運(yùn)動(dòng)的特效,效果甚佳。
這也是router默認(rèn)使用的路由方式。不過(guò),這種方式有一個(gè)弊端,就是在接入第三方的支付的時(shí)候,我們傳入一個(gè)url給到第三方支付作為回調(diào)地址,但是在支付完成以后,有的第三方支付會(huì)把我們的#作為一個(gè)截取符號(hào),僅保留第一個(gè)#符號(hào)前面的url內(nèi)容,后面再添加相應(yīng)的回調(diào)參數(shù)。導(dǎo)致支付完成以后無(wú)法跳轉(zhuǎn)到相應(yīng)的支付頁(yè)面
傳入的url:
http://xx.xx.com/#/pay/123
回調(diào)后的地址:
http://xx.xx.com/pay/123?data=xxxxx%xxxx
2.history模式
還有一種就是history的模式。它是使用h6的history.pushState來(lái)完成URL的跳轉(zhuǎn)的。使用這種方式來(lái)處理跳轉(zhuǎn)的好處就是,url和我們平常看到的沒(méi)有什么區(qū)別。和hash模式作比較的話就是沒(méi)有了#。不過(guò)使用history模式,我們?cè)诤笈_(tái)也要去做相應(yīng)的處理,因?yàn)槿绻苯尤ピL問(wèn)一個(gè)地址,例如http://www.xxxx.com/user/id的時(shí)候,如果后端沒(méi)有配置的時(shí)候,后端就會(huì)返回404頁(yè)面。
4.router-link在循環(huán)中this.參數(shù)名=undefined
<router-link>組件是我們?cè)趘iew層中需要用到的跳轉(zhuǎn)組件。它替代了<a>標(biāo)簽需要做的事情,并且?guī)椭覀冏隽烁嗟氖虑椤?/p>
無(wú)論是 h6 history 模式還是 hash 模式,它的表現(xiàn)行為一致,所以,當(dāng)你要切換路由模式,或者在 IE9 降級(jí)使用 hash 模式,無(wú)須任何變動(dòng)。
在 HTML5 history 模式下,router-link 會(huì)守衛(wèi)點(diǎn)擊事件,讓瀏覽器不再重新加載頁(yè)面。
當(dāng)你在 HTML5 history 模式下使用 base 選項(xiàng)之后,所有的 to 屬性都不需要寫(xiě)(基路徑)了。
不過(guò)當(dāng)我們?cè)趘-for的循環(huán)中使用了router-link的時(shí)候,一般來(lái)說(shuō),我們需要取的都是循環(huán)里的值,通過(guò)定義的item.xxx就可以取到。如果說(shuō)需要取一個(gè)我們?cè)赿ata中定義的值的時(shí)候,我們是通過(guò)this.foo來(lái)取呢?還是通過(guò)foo來(lái)取呢?還是都可以?
這里的話,我們是不能通過(guò)this.foo來(lái)取的,因?yàn)檫@里的this,不再是指向vue的實(shí)例了,而是指向了[object Window]。所以用this.foo來(lái)取的話,其實(shí)是undefined.
<router-link tag="li" :to="{path:`/user/${item.userID}`}" v-for="(item, index) in userList" :key="index"> //含有固定的值 <p>{{this.foo}}</p> <p>{{foo}}</p> </router-link> data(){ return { foo:'bar', } }
4.vue-router配合axios的使用
初次接觸攔截器這個(gè)概念是在java中,通過(guò)攔截器,我們可以對(duì)用戶的登錄狀態(tài)進(jìn)行更加粒度的操作。而對(duì)于一個(gè)SPA的應(yīng)用來(lái)說(shuō),沒(méi)有了后臺(tái)路由的介入,我們就需要在前端實(shí)現(xiàn)一套自己的登錄狀態(tài)的管理機(jī)制。
最直觀的一點(diǎn)就是,通過(guò)用戶的token來(lái)判斷用戶是否登錄?
router.beforeEach((to, from, next) => { const NOW = new Date().getTime(); if (to.matched.some(r => r.meta.requireAuth)) { if(NOW > store.state.deadLine){ store.commit('CLEAR_USERTOKEN') } if (store.state.message.login === true) { next(); } else { next({ path: '/login', query: {redirect: to.fullPath} }) } } else { next(); } })
上面的代碼中,我們通過(guò)vue-router中的全局守衛(wèi),在導(dǎo)航觸發(fā)的時(shí)候大致做了如下幾件事:
(1)判斷導(dǎo)航的頁(yè)面是否需要登錄
(2)超過(guò)登錄持久期限,清除持久化的登錄用戶token
(3)沒(méi)有超過(guò)登錄期限,判斷是否登錄狀態(tài)
(4)沒(méi)登錄,重定向到登錄頁(yè)面
但是,僅僅這樣是不夠的。因?yàn)橛脩糁苯硬徽WN而直接后臺(tái)運(yùn)行網(wǎng)頁(yè)是很正常的事情,這就導(dǎo)致雖然token是存在的,但是對(duì)于后臺(tái)而言,這個(gè)token是無(wú)效的,過(guò)期的了。所以,我們需要axios配合后臺(tái)給出的狀態(tài)碼來(lái)完善我們的攔截器。
import router from '@/router/routes' axios.interceptors.response.use( success => { switch (success .code) { case -100: router.replace({ path: 'login', query: {redirect: router.currentRoute.fullPath} }) console.warn('注意,登錄已過(guò)期!') break; } return success; }, error => { switch (error.code) { case 404: console.warn('請(qǐng)求地址有誤或者參數(shù)錯(cuò)誤!') break; } return Promise.reject(error.response.data) });
通過(guò)后端給到的登錄過(guò)期狀態(tài)碼,這里以-100為例,我們可以用axios的響應(yīng)攔截器實(shí)現(xiàn),當(dāng)我們的token過(guò)期的時(shí)候,我們將頁(yè)面重定向到登錄頁(yè)面去。
5.巧用replace替換push
在項(xiàng)目中,我有的同事就是一直this.$router.push(...)
,從開(kāi)始push到結(jié)尾。
碰到有的頁(yè)面,比如說(shuō),在選擇地址的時(shí)候需要知道用戶當(dāng)前所在的城市,如果沒(méi)有的話,就是重定向到城市列表頁(yè)面去手動(dòng)選取。選擇完成以后再回到選擇地址的頁(yè)面,如果一直使用push的話,點(diǎn)擊選擇地址的后退時(shí),就會(huì)回退到城市列表頁(yè)。然后造成頁(yè)面間的死循環(huán)。
這里如果使用replace來(lái)操作就沒(méi)有什么問(wèn)題了,問(wèn)題就是我們不應(yīng)該讓城市列表頁(yè)出現(xiàn)在我們的瀏覽歷史里面。
總結(jié)
以上所述是小編給大家介紹的vue-router項(xiàng)目實(shí)戰(zhàn)總結(jié),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。