vue-router項目實戰總結

今天來談談vue項目{vue,vue-router,component}三大神將之一的vue-router。做爲咱們先後端分離很重要的實踐之一,router幫咱們完成了SPA應用間的頁面跳轉。前端

而且,配合axios這樣的第三方庫,咱們能夠實現配合後臺接口的攔截器功能。vue

 

對於一個小型項目而言,router這個文件夾裏面就包含了一個router.js就足夠了,java

可是,當咱們的頁面比較多的時候,咱們就須要分出兩個文件出來:一個定義咱們的路由和組件,另外一個實例化組件,並將路由掛載到vue的實例上。webpack

基本的用法就很少贅述,你們能夠看vue-router的官網,認真過一遍的話,基本使用確定沒什麼問題。ios

1.爲何個人路由不起做用?

這裏有個很是重要的一點就是當咱們去構造VueRouter的實例的時候,傳入的參數的問題。web

import routes from '@/router/router'

const router = new VueRouter({
  routes // (ES6語法)至關於 routes: routes
})

new Vue({
  router
}).$mount('#app')

若是你這裏引入的不是routes,你就要按照下面的方式來寫。vue-router

import vRoutes from '@/router/router'

const router = new VueRouter({
  routes :vRoutes 
})

new Vue({
  router
}).$mount('#app')

 

2.在路由中基於webpack實現組件的懶加載

對於咱們的vue項目,咱們基本都是運用webpack打包的,若是沒有懶加載,打包後的文件將會異常的大,形成首頁白屏,延時嚴重,不利於用戶體驗,而運用懶加載則能夠將頁面進行劃分,webpack將不一樣組件打包成不少個小的js文件。須要的時候再異步加載,優化用戶的體驗,換而言之,有的頁面可能100個用戶只有一兩個會進去,何須把流量花在它身上。axios

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
    }]
}]

 若是某個組件包含了嵌套路由,咱們也能夠將兩個路由打包到一個js chunk中。後端

// 這兩條路由被打包在相同的塊中,訪問任一路由都會延遲加載該路由組件
const orderUser= r => require.ensure([], () => r(require('@/pages/order/user')), 'order')
const payRecord= r => require.ensure([], () => r(require('@/pages/order/payRecord')), 'order')

3.router的模式

對於瀏覽器,咱們的router分爲兩種模式。瀏覽器

1.hash模式(默認)

按照一個uri的基本結構來講,hash模式就是在一個基本的URI的片斷進行的處理。若是拋開SPA的話,比較常見的應用場景就是咱們在作pc商城的時候,會有好比說:商品詳情,評論,商品參數這樣的tab切換,就可使用a標籤配合id使用,加上一點運動的特效,效果甚佳。

這也是router默認使用的路由方式。不過,這種方式有一個弊端,就是在接入第三方的支付的時候,咱們傳入一個url給到第三方支付做爲回調地址,可是在支付完成之後,有的第三方支付會把咱們的#做爲一個截取符號,僅保留第一個#符號前面的url內容,後面再添加相應的回調參數。致使支付完成之後沒法跳轉到相應的支付頁面

傳入的url:
http://xx.xx.com/#/pay/123
回調後的地址:
http://xx.xx.com/pay/123?data=xxxxx%xxxx

 

2.history模式

還有一種就是history的模式。它是使用h5的history.pushState來完成URL的跳轉的。使用這種方式來處理跳轉的好處就是,url和咱們日常看到的沒有什麼區別。和hash模式做比較的話就是沒有了#。不過使用history模式,咱們在後臺也要去作相應的處理,由於若是直接去訪問一個地址,例如http://www.xxxx.com/user/id的時候,若是後端沒有配置的時候,後端就會返回404頁面。

4.router-link在循環中this.參數名=undefined

<router-link>組件是咱們在view層中須要用到的跳轉組件。它替代了<a>標籤須要作的事情,而且幫助咱們作了更多的事情。

  • 不管是 h5 history 模式仍是 hash 模式,它的表現行爲一致,因此,當你要切換路由模式,或者在 IE9 降級使用 hash 模式,無須任何變更。

  • 在 HTML5 history 模式下,router-link 會守衛點擊事件,讓瀏覽器再也不從新加載頁面。

  • 當你在 HTML5 history 模式下使用 base 選項以後,全部的 to 屬性都不須要寫(基路徑)了。

不過當咱們在v-for的循環中使用了router-link的時候,通常來講,咱們須要取的都是循環裏的值,經過定義的item.xxx就能夠取到。若是說須要取一個咱們在data中定義的值的時候,咱們是經過this.foo來取呢?仍是經過foo來取呢?仍是均可以?

這裏的話,咱們是不能經過this.foo來取的,由於這裏的this,再也不是指向vue的實例了,而是指向了[object Window]。因此用this.foo來取的話,實際上是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的使用

 初次接觸攔截器這個概念是在java中,經過攔截器,咱們能夠對用戶的登陸狀態進行更加粒度的操做。而對於一個SPA的應用來講,沒有了後臺路由的介入,咱們就須要在前端實現一套本身的登陸狀態的管理機制。

最直觀的一點就是,經過用戶的token來判斷用戶是否登陸?

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();
  }
})

上面的代碼中,咱們經過vue-router中的全局守衛,在導航觸發的時候大體作了以下幾件事:

(1)判斷導航的頁面是否須要登陸

(2)超過登陸持久期限,清除持久化的登陸用戶token

(3)沒有超過登陸期限,判斷是否登陸狀態

(4)沒登陸,重定向到登陸頁面

可是,僅僅這樣是不夠的。由於用戶直接不正常註銷而直接後臺運行網頁是很正常的事情,這就致使雖然token是存在的,可是對於後臺而言,這個token是無效的,過時的了。因此,咱們須要axios配合後臺給出的狀態碼來完善咱們的攔截器。

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('注意,登陸已過時!')
        break;
    }
    return success;
  },
  error => {
      switch (error.code) {
        case 404:
          console.warn('請求地址有誤或者參數錯誤!')
        break;
      }
    return Promise.reject(error.response.data)
  });

 經過後端給到的登陸過時狀態碼,這裏以-100爲例,咱們能夠用axios的響應攔截器實現,當咱們的token過時的時候,咱們將頁面重定向到登陸頁面去。

 5.巧用replace替換push

在項目中,我有的同事就是一直this.$router.push(...),從開始push到結尾。

碰到有的頁面,好比說,在選擇地址的時候須要知道用戶當前所在的城市,若是沒有的話,就是重定向到城市列表頁面去手動選取。選擇完成之後再回到選擇地址的頁面,若是一直使用push的話,點擊選擇地址的後退時,就會回退到城市列表頁。而後形成頁面間的死循環。

這裏若是使用replace來操做就沒有什麼問題了,問題就是咱們不該該讓城市列表頁出如今咱們的瀏覽歷史裏面。

相關文章
相關標籤/搜索