使用Vue路由Hash模式引發的一場血案
背景
路徑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
,可以右下角點個在看,關注一波公衆號:[前端巔峯]