頁面間大量資料引數傳遞
前言
我們在開發專案中經常會遇到一種問題,就是在前端頁面跳轉時傳遞某些引數,通常我們是通過路由傳遞的,但是如果資料量很多的情況下,會造成路由非常的長,如果在大的話甚至會超出位址列URL的最大限度,這就狗帶了.最近手頭上一個專案的前端剛好遇到這個問題,該專案前端用的是vue2.x.不是什麼大問題,但是之前沒有認真想過解決辦法,於是將解決思路記錄下來了.
位址列URL最大限度
首先我查了不同瀏覽器位址列URL的最大限度.
雖然HTTP協議的RFC規範並沒有詳細規定URL的最大字元長度限制,但實際上,在瀏覽器或者伺服器中總會存在限制的。這裡所說的字元是指ASCII字元。HTTP RFC2616協議沒有規定URL的最大長度,規定伺服器如果不能處理太長的URL,就得返回414狀態碼(Request-URI Too Long)。
微軟 Internet Explorer:微軟幫助網站上說IE7之前(包括IE7)的瀏覽器,對URL的最大長度限制是2,083個字元。Firefox:對於Firefox1.5.x,位址列能顯示的URL最大長度是65,536個字元,但實際上有效的URL最大長度不少於100,000個字元。對於Firefox 3.0.5,mozilla官方論壇上有人測試其URL長度限制為65,000個字元。也有人說Firefox可以支援URL高達2Gbyte的長度(參考),在data URL中可以運用到這樣大資料量的URL。dataURL是一種URL本身包含了實際資料的URL,比如一個圖片、一個HTML網頁或者全部的資料、程式碼等等。僅有Firefox支援dataURL。Safari:
綜上,又在網上找了一個附表:
IE |
URL最大限制是2083個位元組,Path長度最大是2048位元組(Get請求)。 |
Firefox |
65536 |
Safari |
80000以上 |
Opera |
190000位元組以上 |
Chrome |
8182位元組 |
Apache Server |
8192位元組 |
IIS |
16384位元組 |
Perl HTTP::Daemon |
至少8000位元組 |
我的思路
思路一
我的第一個想法就是通過快取進行解決----cookie/localStorage/sessionStorage.通過在伺服器或客戶端進行資料快取以供頁面進行讀取.但是在後續的思考中我想到首先cookie快取量很小,同時session/cookie對與網站所有頁面是透明的,我只是想實現指定頁面間進行引數傳遞,其他頁面應該不知情,考慮到保密性,我放棄了這個想法.
思路二
我的第二個思路還是通過快取來實現,但是是通過application cache(共享本地快取),具體的介紹就不在這裡說了.但是我考慮到application cache具有快取時間,而我想要的是在頁面跳轉後快取的引數資料被銷燬,也就是類似快閃記憶體的機制.同時application cache快取頁面需要的資源,那麼其他頁面所需要的資源也同時被快取下來,這樣做得不償失.
思路三
通過js的全域性變數.這個沒什麼介紹的,將引數儲存在全域性變數中,那麼在頁面宣告週期內所有頁面都可以使用.但是還是那個問題,在使用全域性變數的時候,其他頁面也能夠獲得.所以pass.
思路四
我找到利用原生很不錯的方法,那就是通過模態視窗來實現頁面間的引數傳遞.以下是對showModalDialog(模態視窗)的簡單介紹:
基本介紹:
showModalDialog() (IE 4+ 支援) showModelessDialog() (IE 5+ 支援) window.showModalDialog() 方法用來建立一個顯示HTML內容的模態對話方塊。 window.showModelessDialog() 方法用來建立一個顯示HTML內容的非模態對話方塊。
vReturnValue = window.showModalDialog(sURL [, vArguments] [,sFeatures])
vReturnValue = window.showModelessDialog(sURL [, vArguments] [,sFeatures])
sURL -- 必選引數,型別:字串。用來指定對話方塊要顯示的文件的URL。 vArguments -- 可選引數,型別:變體。用來向對話方塊傳遞引數。傳遞的引數型別不限,包括陣列等。對話方塊通過 window.dialogArguments來取得傳遞進來的引數。 sFeatures -- 可選引數,型別:字串。用來描述對話方塊的外觀等資訊,可以使用以下的一個或幾個,用分號“;”隔開。
1. dialogHeight: 對話方塊高度,不小於100px 2. dialogWidth: 對話方塊寬度。 3. dialogLeft: 離螢幕左的距離。 4. dialogTop: 離螢幕上的距離。 5. center: { yes | no | 1 | 0 } : 是否居中,預設yes,但仍可以指定高度和寬度。 6. help: {yes | no | 1 | 0 }: 是否顯示幫助按鈕,預設yes。 7. resizable: {yes | no | 1 | 0 } [IE5+]: 是否可被改變大小。預設no。 8. status: {yes | no | 1 | 0 } [IE5+]: 是否顯示狀態列。預設為yes[ Modeless]或no[Modal]。 9. scroll: { yes | no | 1 | 0 | on | off }:是否顯示滾動條。預設為yes。 ...
通過vArguments來進行傳遞的。型別不限制,對於字串型別,最大為4096個字元。也可以傳遞物件,如下:
test.html:
var obj=new Object();
obj.name="qiubinchao";
obj.tel="12345678";
window.showModalDialog('./testb.html',obj,"dialogWidth:500px;dialogHeight:550px");
window.location.href="./testb.html";
testb.html:
var obj = window.dialogArguments
console.log(window.dialogArguments);
test.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> show(); function AddNew() { if(!window.showModalDialog) { window.showModalDialog=function(url,name,option){ if(window.hasOpenWindow){ window.newWindow.focus(); } var re = new RegExp(";", "g"); var option = option.replace(re, '","'); //把option轉為json字串 var re2 = new RegExp(":", "g"); option = '{"'+option.replace(re2, '":"')+'"}'; option = JSON.parse(option); var openOption = 'width='+parseInt(option.dialogWidth)+',height='+parseInt(option.dialogHeight)+',left='+(window.screen.width-parseInt(option.dialogWidth))/2+',top='+(window.screen.height-30-parseInt(option.dialogHeight))/2; window.hasOpenWindow = true; window.newWindow = window.open(url,name,openOption); } } } function show() { var obj=new Object(); obj.name="qiubinchao"; obj.tel="12345678"; AddNew(); window.showModalDialog('./testb.html',obj,"dialogWidth:500px;dialogHeight:550px"); window.location.href="./testb.html"; } </script> </body> </html>
- 怎樣才讓在showModalDialog和showModelessDialog的超連線不彈出新視窗?
在被開啟的網頁里加上:
<base target="_self">
- 怎樣才重新整理showModalDialog和showModelessDialog裡的內容?
在showModalDialog和showModelessDialog裡是不能按F5重新整理的,又不能彈出選單。這個只能依靠javascript了,以下是相關程式碼:
<body onkeydown="if (event.keyCode==116){reload.click()}"> <a id="reload" href="filename.htm" style="display:none">reload...</a>
- 如何用javascript關掉showModalDialog(或showModelessDialog)開啟的視窗。
<input type="button" value="關閉" onclick="window.close()">
也要配合<base target="_self">,不然會開啟一個新的IE視窗,然後再關掉的。
- Math.random與showModalDialog。
當你設定的彈出網頁固定時(如上面的"modal.htm"頁面),ie很可能到臨時檔案區,下載上次產生的該頁面(openPage.html),而沒有重新載入,對於動態載入的頁面來說,這樣往往產生誤會,如沒有及時更新資料,也就更不利於開發者測試。所以,你可以採用如下方式:
var strPage = “/medal.htm?random="+Math.random();
這樣每次產生的strPage是不一樣的.
但是最後我還是放棄了,因為首先我用的是vue框架,寫原生太不優雅;其次如上所示,使用模態視窗的侷限性太大.
思路五
俗話說:解鈴還須繫鈴人
在一籌莫展之際,我想到了vue-router中的params.上程式碼:
傳參:
this.$router.push({name:'/send/sendHome', params: {setStr: this.multipleSelection}});
接收引數:
let setArray = this.$route.params.setStr;
query傳遞引數:
傳參:
this.$router.push({
path:'/xxx'
query:{
id:id
}
})
接收引數:
this.$route.query.id
注意:無論是params還是query進行引數傳遞,傳參是this.$router,接收引數是this.$route,一定要細心.
區別:
1.當使用query進行引數傳遞時,引數會跟在路徑後面.我們可以在位址列看到後面跟的引數,而params不會在位址列顯示.直白的說query相當於get請求,而params相當於post請求.
2.params傳參,push裡面只能是 name:'xxxx',不能是path:'/xxx',因為params只能用name來引入路由,如果這裡寫成了path,接收引數頁面會是undefined.
果然...自己挖的坑還要自己填...