3.4,、iframe+location.hash
這種方法比上面兩種稍微繁瑣一點,原理如下:
www.下的a.html想和www.下的b.html通信(在a.html中動態(tài)創(chuàng)建一個b.html的iframe來發(fā)送請求),;
但是由于“同源策略”的限制他們無法進行交流(b.html無法返回數(shù)據),,于是就找個中間人:www.下的c.html(注意是www.下的),;
b.html將數(shù)據傳給c.html(b.html中創(chuàng)建c.html的iframe),由于c.html和a.html同源,,于是可通過c.html將返回的數(shù)據傳回給a.html,,從而達到跨域的效果。
三個頁面之間傳遞參數(shù)用的是location.hash(也就是www.a.html#sayHello后面的’#sayHello’),,改變hash并不會導致頁面刷新(這點很重要),。
具體代碼如下:
www./a.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| //通過動態(tài)創(chuàng)建iframe的hash發(fā)送請求
function sendRequest(){
var ifr = document.createElement( 'iframe' );
ifr.style.display = 'none' ;
//跨域發(fā)送請求給b.html, 參數(shù)是sayHello
document.body.appendChild(ifr);
}
//獲取返回值的方法
function checkHash() {
var data = location.hash ?
location.hash.substring(1) : '' ;
if (data) {
//處理返回值
alert(data);
location.hash= '' ;
}
}
//定時檢查自己的hash值
setInterval(checkHash, 2000);
window.onload = sendRequest;
|
www./b.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| function checkHash(){
var data = '' ;
//模擬一個簡單的參數(shù)處理操作
switch (location.hash){
case '#sayHello' : data = 'HelloWorld' ; break ;
case '#sayHi' : data = 'HiWorld' ; break ;
default : break ;
}
data && callBack( '#' +data);
}
function callBack(hash){
// ie、chrome的安全機制無法修改parent.location.hash,,
// 所以要利用一個中間的www.域下的代理iframe
var proxy = document.createElement( 'iframe' );
proxy.style.display = 'none' ;
// 注意該文件在"www."域下
document.body.appendChild(proxy);
}
window.onload = checkHash;
|
www./c.html
1
2
3
4
5
| //因為c.html和a.html屬于同一個域,,
//所以可以改變其location.hash的值
//可通過parent.parent獲取a.html的window對象
parent.parent.location.hash =
self.location.hash.substring(1);
|
可能有人會有疑問,既然c.html已經獲取了a.html的window對象了,,為何不直接修改它的dom或者傳遞參數(shù)給某個變量呢,?
原因是在c.html中修改 a.html的dom或者變量會導致頁面的刷新,a.html會重新訪問一次b.html,,b.html又會訪問c.html,,造成死循環(huán)……囧呀~
所以只能通過location.hash了。這樣做也有些不好的地方,,諸如數(shù)據容量是有限的(受url長度的限制),,而且數(shù)據暴露在url中(用戶可以隨意修改)……
3.5、postMessage(html5)
html5中有個很酷的功能,,就是跨文檔消息傳輸(Cross Document Messaging)。新一代瀏覽器都將支持這個功能:Chrome 2.0+,、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ ,。
使用方法如下:
1
| otherWindow.postMessage(message, targetOrigin);
|
說明:
- otherWindow: 對接收信息頁面的window的引用??梢允琼撁嬷衖frame的contentWindow屬性,,window.open的返回值等。
- message: 所要發(fā)送的數(shù)據,,string類型,。
- targetOrigin: 用于限制otherWindow,“*”表示不作限制,。
www./a.html中的代碼:
html:
script:
1
2
3
4
5
6
| window.onload = function () {
var ifr = document.getElementById( 'ifr' );
ifr.contentWindow.postMessage( 'sayHello' , targetOrigin);
};
|
www./b.html的script
1
2
3
4
5
6
7
8
| //通過message事件來通信,,實在太爽了
window.addEventListener( 'message' , function (e){
// 通過origin屬性判斷消息來源地址
e.data== 'sayHello' ) {
alert( 'Hello World' );
}
}, false );
|
3.6、使用flash
由于本人對flash不怎么熟悉,,此處暫時忽略之~
3.7,、Cross Frame
行文至此,突然在口碑網UED博客上看到了一篇 《跨域資源共享的10種方式》,,對跨域的多種方法都有介紹(雖然有源碼,,但多數(shù)都是直接調用YUI庫的,,比較難看出原理)。
里面提到了Cross Frame這種方法,,似乎挺不錯的,,改日一定翻源碼來研究。
4,、總結
研究了幾天,,雖然對多種跨域方法都有所了解了,但是真要投入應用還是明顯不夠的(還是需要借助一些js庫),。
每種方法都有其優(yōu)缺點,,使用的時候其實應該將多種跨域方法進一步封裝一下,統(tǒng)一調用的接口,,利用js來自動判斷哪種方法更為適用 ,。