vue router 需要go(-2)才能返回前一頁


背景:

團隊內遇到了好幾次了,比如新建跳轉到頁面后,$router.go(-2)才能返回列表頁面,並且query內寫的參數的key也沒了,所以趁着今天有時間就解決了一下,分享一下。

先說一下問題所在,方便大家先拿去測試,如果對了,那就是俺蒙對了;如果不對,那就是俺太菜了。

問題所在:

router的query為undefined(目前就發現這一種),就會導致vueRouter內部報錯,但是我沒聽說過有這種說法,所以我去跟着源碼走了一圈,發現有一個pushState,try和catch走catch了,所以走了兩遍router.push(沒去細看router哪里有捕獲這個錯誤的,只能看到這里執行兩次push)。

解決方法:

假設問題代碼如下:

// this.age = undefined
// this.name = jin
this.$router.push({
  path: '/user',
  query: {
    name: this.name,
    age: this.age
  }
})

解決辦法如下:

  1. 吧query改為path后面拼接(不建議), 如下:
this.$router.push({
  path: `/user?name=${this.name}&age=${this.age}`
})
  1. query內增加兼容處理,如下:
this.$router.push({
  path: '/user',
  query: {
    name: this.name || '',
    age: this.age || ''
  }
})

第二種方法比較正規,並且如果和我們一樣對router進行封裝了的話,這樣的判斷處理可以放到通用的地方,就像我們好多處都有這個問題,一下就解決了。

我排查的過程:

這部分是我對這個問題的原理問題分析,不對的地方,希望大佬們指出。

  1. 為什么參數丟失了

45F3B7B6D5F677973FF09BF9A2F1BEAF.jpg

vue中處理query參數的地方,這個函數作用看名字就可以看出來是將query轉換為stringify,我們可以看到當value為undefined時候直接return不進行處理

  1. hash方法源碼
HashHistory.prototype.push = function push(location, onComplete, onAbort) {
    var this$1 = this;
    var ref = this;
    var fromRoute = ref.current;
    this.transitionTo(location, function(route) {
        pushHash(route.fullPath);
        handleScroll(this$1.router, route, fromRoute, false);
        onComplete && onComplete(route);
    }, onAbort);
};
  1. 這個問題的根源

細節的原因,我懶得去跟蹤了,可以確定一個大概的路。

排查的時候,我發現如果有問題,其實都會觸發兩次上面的push方法,並且吧第二次吧undefined參數去掉了。

報錯的地方為,下面這段代碼的try/catch, 重新對導航執行了一次assign,而route可以監聽每一次location的操作,所以造成了push兩次的問題(這個我也想不明白為啥會進catch但是通過瀏覽器可以看到確實進了catch,但是e打印也是undefined)

function pushState(url, replace) {
    saveScrollPosition();
    // try...catch the pushState call to get around Safari
    // DOM Exception 18 where it limits to 100 pushState calls
    var history = window.history;
    try {
        if (replace) {
            // preserve existing history state as it could be overriden by the user
            var stateCopy = extend({}, history.state);
            stateCopy.key = getStateKey();
            history.replaceState(stateCopy, '', url);
        } else {
            history.pushState({
                key: setStateKey(genStateKey())
            }, '', url);
        }
    } catch (e) {
        window.location[replace ? 'replace' : 'assign'](url);
    }
}

最后,希望能對大家有所幫助吧。如分析不對,還請大佬幫忙指出問題所在


免責聲明!

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



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