Vue Router路由守衛妙用:異步獲取數據成功后再進行路由跳轉並傳遞數據,失敗則不進行跳轉


問題引入

試想這樣一個業務場景:

在用戶輸入數據,點擊提交按鈕后,這時發起了ajax請求,如果請求成功,
則跳轉到詳情頁面並展示詳情數據,失敗則不跳轉到詳情頁面,只是在當前頁面給出錯誤消息。

難點所在

需要注意的是,這里並沒有單獨的接口用於判斷用戶是否通過校驗,而是若用戶通過校驗,接口就直接返回了用戶需要的詳情信息,未通過校驗則不會返回詳情信息並報錯。

常見方案問題分析

(一)用戶點擊按鈕后直接跳轉到詳情頁面,在詳情頁面的created鈎子函數中發起ajax請求獲取數據
問題在於:

若用戶未通過校驗,也會先跳轉到詳情頁面,然后再報錯,
而我們的目標是先判斷是否成功,成功了再進行路由跳轉。

(二)將詳情頁面寫在彈窗中,不進行路由跳轉。在當前頁面發起請求,成功則在彈窗中展示詳情數據,失敗了則不展示彈窗
問題在於:

彈窗中的內容特別多的情況下,排版不容易,很容易難看,畢竟彈窗一般適用於展示少量數據 ,
並且產品的設計要求可能就是需要單獨頁面展示,不允許使用彈窗。
另外,如果路由和頁面都已經寫好了,再去寫彈窗也會額外增加不少工作量

(三)發兩次請求:當前頁面發起第一次請求,失敗了不進行跳轉;成功了在詳情頁面再發起一次請求,獲取詳情數據

這種方式肯定可行,但是問題在於:

同一個api發送了兩次請求,多發一次請求白白耗費了網絡資源

(四)當前頁面發起請求,失敗了進行錯誤提示;成功了,則跳轉到詳情頁面,並通過Vuex或者空組件實現非父子組件通信的方式將數據攜帶至詳情頁面展示
這種方式的問題在於:

Vuex的設計目標是存儲系統各組件共用的狀態,例如用戶登錄狀態、菜單伸縮收起狀態,
這里僅有兩個組件,采用Vuex有種大炮打蚊子的感覺,使用空組件事件傳值實現非父子組件通信
會略顯繁瑣。並且這兩種方式加大了系統復雜度,也容易有新坑。

(五)瀏覽器緩存
不用說,更加繁瑣了,也偏離更遠了。

推薦解決方案:使用Vue Router的beforeRouteEnter路由導航守衛

(一)beforeRouteEnter簡介:

它本質上,類似於Vue.js的生命周期鈎子函數。它在新路由被確認前被調用,可以在里面進行數據處理,發起ajax獲取數據,甚至是取消導航。當調用該守衛時,頁面仍停留在原頁面。該守衛執行完畢后(包括異步獲取數據),才會跳轉到新頁面。

(二)使用案例

在詳情組件中使用beforeRouterEnter路由守衛:

import $axios from '@/libs/axios';
import api from '@/api';  

export default {
  name:'testComponent',
  data(){
  	return {};
  },
  beforeRouteEnter(to, from, next) {
    $axios
      .get(api.GetQueueSettingDetail, {
        params: {
          waybillKey: to.params.pickCode,
          warehouseType: 11
        }
      })
      .then(resp => {
        if (resp.success) {
          next(vm => {
            vm.carInfo = resp.result;
          });
        } else {
          next(false);
        }
      })
      .catch(() => {
        next(false);
      });
  },
}

在以上案例中,在新路由被確認前,先發起ajax請求,若成功,就將數據賦值給該組件的carInfo,並跳轉到新路由。若失敗,調用next(false)回調函數取消導航,頁面仍停留在原頁面。
該方案相對來說,比較圓滿的實現了開篇所提的業務需求,並且沒有額外的開銷。

(三)參數說明

三個參數

  • to 即將要進入的目標 路由對象
  • from 當前導航正要離開的路由
  • next 回調函數,一定要調用該方法來 resolve 這個鈎子,可以在里面取消導航(next(false))或進行數據處理

(四) 注意事項

  • beforeRouteEnter 守衛 不能 訪問 this,因為守衛在導航確認前被調用,因此即將登場的新組件還沒被創建。因而上面示例中api和axios都采用了手動導入,沒有使用this.axios或者this.api的方式。
  • 訪問組件實例的方式是,通過傳一個回調給 next來訪問組件實例,也不能使用this。在上面示例中,獲取數據成功后,使用的是vm.carInfo而不是this.carInfo。
  • next(false)的作用是取消導航,這時,一切操作都停留在原頁面,看起來就像什么也沒發生一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM