背景

路徑1:

https://xxxxx.djtest.cn/driver-register/index.html?hmsr=qqqqq#/register

路徑2:

https://xxxxx.djtest.cn/driver-register/index.html#/register?hmsr=qqqqq

大家平常用那個什麼格式的鏈接,路徑1還是路徑2????

我一直習慣用路徑2,可是就在前不久出現了一個線上bug:sob::sob::sob:。這個bug原因還是路徑不規範造成的,當是我一臉懵逼,我是誰,我在哪????

url的組成

協議部分、域名部分、端口部分、虛擬目錄部分、文件名部分、參數部分、錨部分

注:端口不是一個URl必須的部分,如果省略端口部分,將採用默認端口。

相信大家對於url每一部分都很瞭解。在這就簡單提一下,就不浪費大家的時間了。

使用中遇到的問題

問題1:

【路徑1】和【路徑2】都能正常打開頁面,它們的區別是什麼,誰纔是規範的url?

【路徑1】錨部分

【路徑2】錨部分

通過控制檯的輸出,我們發現兩個路徑打印出來的參數部分和錨部分是不一樣,爲啥??

url的錨部分是從“#”開始到最後,都是錨部分。錨部分不是url的必需部分。 url的參數部分是從“?”開始到“#”爲止之間的部分。參數部分也不是url的必需部分。根據url參數部分和錨部分的定義以及控制檯輸出的結果,我們可以得出【路徑1】是符合規範url。

問題2:

由問題1得出【路徑1】是符合url規範的路徑。但是在開發中我發現問題又來了,用this.$route.query 無法獲取參數?在頁面中增加代碼(如下)

created() {

console.log('*******************')

console.log('this.$route.query.hmsr:'+this.$route.query.hmsr)

console.log('window.location.search:'+window.location.search)

console.log('*******************')

}

查看打印結果

【路徑1】:

【路徑2】:

why???

我查閱vue router相關文檔,對此並沒有說明,自己猜想應該是vue router內部做了相應的處理。

問題就來了,我們應該在項目中如何獲取參數呢?

寫一個獲取參數的通用方法:

function getUrlParam(key) {

var url = window.location.href;

var startIndex = url.indexOf('?');

var params = {};

if (startIndex > -1) {

var str = url.substring(startIndex + 1);

var arr = str.split('&');

for (var i = 0; i < arr.length; i++) {

var kv = arr[i].split('=');

if (kv[1].indexOf('#') > -1) {

kv[1] = kv[1].substring(0, kv[1].indexOf('#'));

}

params[kv[0]] = kv[1];

}

}

return params[key];

}

【路徑1】

【路徑2】

注意:在傳統模式開發中,如果在url中search與hash同時存在,你的hash值一定要放在search後面。

問題3:

通過上面獲取參數方法,【路徑1】和【路徑2】都能獲取到了對應的參數,這回沒有問題了吧,但是想象很美好,現實很殘酷。

現實是這樣的,h5頁面放到app中時,會在配置的路徑上添加一些參數。app開發人員添加規則是在錨部分的前面添加參數。但是如果我們的頁面使用vue-router進行頁面跳轉同時增加參數,url上就會出現雙“ ?”的情況,那參數還能獲取嗎?

怎麼辦後面一個問號的參數獲取不到?

方案一:優化獲取參數函數,使其能獲取多問號的參數

function getUrlAllParam(...args) {

if (args.length === 0) return undefined

const url = decodeURIComponent(window.location.href)

const reg = args.length === 1

? new RegExp(`[&?]${args[0]}=([^&%#]+)`)

: new RegExp(`[&?](?:${args.join('|')})=([^&%#]+)`)


const matchArray = url.match(reg)


return matchArray === null ? undefined : matchArray[1]

}

調用:

this.getUrlAllParam('hmsr') //獲取參數的key

方案二: 不使用vue router跳轉。跳轉之前把要跳轉的路徑拼接好,再跳轉,讓路徑中不存雙問好的問題。

fomartUrl(url,params,hash){

// url 是訪問路徑 字符串(不包含參數部分和錨部分的)

// params 參數是數組[{name:'hmsr',value:'1222'}]

if(!url){

return false;

}

let query = '';

if(params && params.length>0){

let queryAttr =[];

for(let i =0;params.length>i;i++){

queryAttr.push(params[i].name + '=' +params[i].value)

}

query = queryAttr.join('&')

}

if(hash){

return url + '?' + query + '#/' + hash

} else {

return url + '?' + query

}

}


調用:

const goHref = this.fomartUrl(

'http://localhost:8080/',

[{name:'hmsr',value:'2222'},{name:'aaa',value:'11'}],

'outsideIndex')


window.location.href = goHref

總結

這是在開發過程中,遇到的一些與url參數部分和錨部分相關的問題以及自己的解決方案。各位大佬如果有更好解決方案,歡迎加羣指導交流。

  • 如果感覺寫得不錯,關注下微信公衆號  [前端巔峯]
  • 我是 Peter ,架構設計過20萬人端到端加密超級羣功能的桌面IM軟件,我微信: CALASFxiaotan
  • 另外歡迎收藏我的資料網站:前端生活社區: https://qianduan.life ,可以右下角點個在看,關注一波公衆號: [前端巔峯]
相關文章