1. 程式人生 > >頁面間大量數據參數傳遞

頁面間大量數據參數傳遞

obj 至少 非模態 數據量 save 遇到 參數說明 center topic

前言

我們在開發項目中經常會遇到一種問題,就是在前端頁面跳轉時傳遞某些參數,通常我們是通過路由傳遞的,但是如果數據量很多的情況下,會造成路由非常的長,如果在大的話甚至會超出地址欄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:


Safari最少支持80,000個字符長度的URL。
Opera:
Opera官方網站上說,Opera並沒有強制限制URL的長度。
網友測試Opera 9支持最少190,000個字都長度的URL,並且Opera9的地址欄可以顯示、編輯、復制和粘貼完整的URL串。

綜上,又在網上找了一個附表:

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     -- 可選參數,類型:字符串。用來描述對話框的外觀等信息,可以使用以下的一個或幾個,用分號“;”隔開。
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。

...
使用showModalDialog進行參數傳遞:

通過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);
一個問題:在chrome37後,showModalDialog被chrome禁了,這就很尷尬了,但是有解決的辦法:
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">
就可以了。這句話一般是放在<head>之間的。
  • 怎樣才刷新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>
將filename.htm替換成網頁的名字然後將它放到你打開的網頁裏,按F5就可以刷新了,註意,這個要配合<base target="_self">使用,不然你按下F5會彈出新窗口的。
  • 如何用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;
vue-router中無論是params/query(路由對象屬性)都支持參數傳遞,但是我的毛病又犯了,這兩個有什麽區別呢?

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.

果然...自己挖的坑還要自己填...

頁面間大量數據參數傳遞