window.name 跨域

admin發表於2019-07-07

window.name屬性非常的簡單,它能夠設定或者獲取當前視窗物件的名稱。

關於它的基本用法可以參閱window.name 用法一章節。

但是此屬性的某些特點,又讓其有了其他使用價值,那就是跨域操作。

特別說明:如果不考慮瀏覽器相容性,更加推薦採用window.postMessage()實現跨域。

一.為什麼可以進行跨域操作:

每一個頁面都對應一個window視窗,一個視窗可以開啟不同的頁面。

無論這些頁面同域還是不同域,它們都共享一個window.name,這一點是實現跨域的關鍵。

window.name屬性可以容納的資料大小大致是2M,資料量還是可以的,不同的瀏覽器可能會有所不同。

關於什麼是跨域可以參閱同源策略詳解一章節。

下面對window.name屬性的特性進行一下驗證操作:

(1).首先在一個視窗開啟螞蟻部落(www.softwhy.com)。

(2).然後在谷歌開發者工具控制檯設定window.name的值為"螞蟻部落":

a:3:{s:3:\"pic\";s:43:\"portal/201907/07/142023wn8um7nnofb7s3v8.jpg\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

(3).然後在同一個視窗開啟百度的首頁,很明顯這不同域的。

在此視窗下的控制檯獲取設定的window.name屬性值:

a:3:{s:3:\"pic\";s:43:\"portal/201907/07/142039gh1m3mm75osx7xms.jpg\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

可以看到無論是否同域,都會共享一個window.name。

二.實現跨域操作:

通過下面的程式碼例項簡單演示一下利用window.name實現跨域操作。

假設有如下三個頁面:

(1).x.com/getDate.html:獲取資料的頁面

(2).x.com/proxy.html:代理頁面,與獲取資料頁面同域

(3).y.com/date.html:資料頁面,getDate.html將從其獲取資料

我們的需求是getDate.html利用window.name從date.html頁面獲取相關資料。

date.html頁面中的資料如下:

[JavaScript] 純文字檢視 複製程式碼
let date = {
    webName:"螞蟻部落",
    address:"青島市南區"
}
window.name = date;

window.name資料可以共享,當前視窗載入date.html頁面後,再載入getDate.html頁面。

getDate.html頁面可以獲取date.html中設定的資料,但是總不能採取如下兩種措施:

(1).date.html有程式碼可以在同一視窗跳轉到getDate.html頁面。

(2).開啟date.html頁面,然後再手動在同一視窗開啟getDate.html頁面。

上述兩種方式過於死板,在實際專案中使用不太現實,不過可以利用<iframe>另闢蹊徑。

實現跨域操作步驟如下:

(1).在getDate.html頁面建立一個隱藏的<iframe>:

動態建立一個<iframe>,並將其設定為隱藏狀態,不影響頁面的正常佈局。

並將此<iframe>的src屬性值設定為y.com/date.html,那麼框架的window.name會獲取到對應的資料。

(2).監聽<iframe>的load事件,進行相應操作:

由於是跨域getDate.html頁面無法獲取在<iframe>載入的y.com/date.html中的資料。

但是可以當y.com/date.html頁面在框架中載入完成之後,再在框架載入proxy.html頁面。

由於proxy.html和getDate.html共享window.name,並且proxy.html與getDate.html是同域的。

(3).核心程式碼展示:

下面給出操作的核心程式碼部分,比較簡單:

[JavaScript] 純文字檢視 複製程式碼
let state = 0, 
    iframe = document.createElement('iframe'),
    loadfn = ()=> {
        if (state === 1) {
            // 讀取資料
            let data = iframe.contentWindow.name;    
            // 其他程式碼
        } else if (state === 0) {
            state = 1;
            // 載入同域代理檔案
            iframe.contentWindow.location = "http://x.com/proxy.html"; 
        }  
    };

iframe.src = 'http://y.com/date.html';
if (iframe.attachEvent) {
  iframe.attachEvent('onload', loadfn);
} else {
  iframe.onload  = loadfn;
}
document.body.appendChild(iframe);

上述程式碼比較簡單,下面做簡略說明:

(1).動態建立一個iframe,並初始化一個狀態標記state。

(2).初始設定iframe載入跨域date.html頁面。

(3).通過load事件監聽iframe載入的頁面是否已經載入完成,如果完成則執行loadfn函式。

(4).首先載入的是跨域資料檔案,載入完成後執行loadfn函式,如果state等於0,那說明沒有載入同域代理檔案,於是通過iframe.contentWindow.location = "http://x.com/proxy.html"在iframe視窗載入同域代理檔案,並將 state值設定為1。

(5).如果同域代理檔案在iframe中載入完成,再次出發load時間,再執行loadfn函式,此時state變為1,表示同域代理檔案載入完成,你可以順暢的獲取資料了。

刪除iframe:

當我們獲取資料並進行相關操作完畢後,那麼動態建立的iframe也就無用了。

可以通過如下JavaScript將其刪除:

[JavaScript] 純文字檢視 複製程式碼
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);

上面的程式碼都是一些核心演示,需要根據自己的需要進行改造。

相關文章