第一篇文章寫了關(guān)于跨域最常用的三種方法,即JSONP症革、cors筐咧、服務(wù)器代理,那么今天我們繼續(xù)講解另外三種根據(jù)iframe框架來實(shí)現(xiàn)的跨域請求方式。
location.hash
1.1問題描述
本地頁面a1.html要訪問異域a2.html的數(shù)據(jù)
1.2環(huán)境配置
a1.html 和 a3.html我們放在express中的app.js運(yùn)行
地址分別為:http://localhost:3000/a1.html和http://localhost:3000/a3.html
a2.html 的代碼量蕊,我放在http://localhost:3001/a2.html中
1.3原理
a1.html通過iframe跨域加載了a2.html的頁面铺罢,如果a1有hash,那么a2獲取數(shù)據(jù)危融,但是因?yàn)閍1和a2不同源畏铆,且a2iframe是a1的子頁面,所以a1無法從a2身上拿到任何數(shù)據(jù)吉殃;解決辦法是辞居,a2把數(shù)據(jù)通過hash和iframe傳給a3;a3和a1同源蛋勺,就可以把數(shù)據(jù)傳給a1的hash了
- a1.html頁面的前端設(shè)置
<script>
let ifr=document.createElement('iframe');
ifr.src='http://localhost:3001/a2.html#data';
document.body.appendChild(ifr);
ifr.style.display='none';
window.addEventListener('hashchange',e=>{
let data=location.hash.substring(1);
console.log(data)
})
</script>
- 異域a2.html頁面的前端設(shè)置
<script>
switch(location.hash){
case '#data':
callback();
break;
}
function callback() {
let data = '數(shù)據(jù)數(shù)據(jù)數(shù)據(jù)'
try {
window.parent.location.hash = '#' + data;
}
catch(e){
let ifr = document.createElement('iframe');
ifr.src = 'http://localhost:3000/a3#' + data;
document.body.appendChild(ifr);
ifr.style.display='none';
}
}
</script>
- 同域a3.html的前端設(shè)置
<script>
window.parent.parent.hash=self.location.hash;
</script>
window.name
window對象有個name屬性瓦灶,該屬性有個特征:即在一個窗口(window)的生命周期內(nèi),窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權(quán)限抱完,window.name是持久存在一個窗口載入過的所有頁面中的贼陶,并不會因新頁面的載入而進(jìn)行重置。
1.1問題描述
本地頁面b1.html要訪問異域b2.html的數(shù)據(jù)
1.2環(huán)境配置
b1.html 和 b3.html我們放在express中的app.js運(yùn)行
地址分別為:http://localhost:3000/b1.html和http://localhost:3000/b3.html
b2.html 的代碼巧娱,我放在http://localhost:3001/b2.html中
1.3原理
b1.html通過iframe框架加載一個b2.html頁面碉怔,h2.html有window.name=data,但是因?yàn)槭钱愑蜻@個數(shù)據(jù)h1.html拿不到禁添,所以讓b2.html讓iframe指向同域的b3.html撮胧,通過b3.html拿到數(shù)據(jù)
- b1.html前端設(shè)置
<iframe src="http://localhost:3001/b2" frameborder="0"></iframe>
let ifr=document.getElementsByTagName('iframe')[0];
ifr.style.display='none';
ifr.onload=function(){//加載b2
ifr.src='http://localhost:3000/b3';
ifr.onload=function(){//加載b3
console.log(contentWindow.name)
}
}
- 異域b2.html前端設(shè)置
window.name='這是window.name請求跨域的數(shù)據(jù)'
- 同域的b3.html頁面不需要任何設(shè)置
postMessage
window.postMessage(message,targetOrigin) 方法是html5新引進(jìn)的特性,可以使用它來向其它的window對象發(fā)送消息老翘,無論這個window對象是屬于同源或不同源芹啥,目前IE8+、FireFox铺峭、Chrome墓怀、Opera等瀏覽器都已經(jīng)支持window.postMessage方法。
調(diào)用postMessage方法的window對象是指要接收消息的那一個window對象卫键,該方法的第一個參數(shù)message為要發(fā)送的消息傀履,類型只能為字符串;第二個參數(shù)targetOrigin用來限定接收消息的那個window對象所在的域莉炉,如果不想限定域钓账,可以使用通配符 * 。
需要接收消息的window對象呢袱,可是通過監(jiān)聽自身的message事件來獲取傳過來的消息官扣,消息內(nèi)容儲存在該事件對象的data屬性中。
上面所說的向其他window對象發(fā)送消息羞福,其實(shí)就是指一個頁面有幾個框架的那種情況惕蹄,因?yàn)槊恳粋€框架都有一個window對象。在討論第二種方法的時候,我們說過卖陵,不同域的框架間是可以獲取到對方的window對象的遭顶,而且也可以使用window.postMessage這個方法。
1.1問題描述
本地頁面c1.html要訪問異域c2.html的數(shù)據(jù)
1.2環(huán)境配置
c1.html的地址:http://localhost:3000/c1.html
c2.html 的地址泪蔫,http://localhost:3001/c2.html
1.3原理
- 給iframe上的window調(diào)用postMessage(data棒旗,origin)
- 通過觸發(fā)window上的message事件,來接受數(shù)據(jù)
- 通過parent.postMessage()繼續(xù)發(fā)送數(shù)據(jù)
- 通過觸發(fā)window上的message事件撩荣,來接受數(shù)據(jù)
- c1.html的前端設(shè)置
<iframe src="http://localhost:3001/c2" frameborder="0"></iframe>
<script>
window.onload=function(){
let targetOrigin='http://localhost:30001';
window.frames[0].postMessage('這是c1傳給c2的數(shù)據(jù)',targetOrigin)
};
window.addEventListener('message',e=>{
console.log('c1已結(jié)接收到c2的數(shù)據(jù)'+e.data)
})
</script>
- c2.html的前端設(shè)置
<iframe src="http://localhost:3001/c2" frameborder="0"></iframe>
<script>
window.onload=function(){
let targetOrigin='http://localhost:3001';
window.frames[0].postMessage('這是c1傳給c2的數(shù)據(jù)',targetOrigin)
};
window.addEventListener('message',e=>{
console.log('c1已結(jié)接收到c2的數(shù)據(jù)'+e.data)
})
</script>