新手學跨域之iframe

頁面嵌套iframe是比較常見的,好比QQ相關業務頁面的登陸框通常都是iframe的。使用ifrmae跨域要知足一個基本條件,父頁面和子頁面都是本身能夠控制的,若是隨便把iframe指向一個其餘網站,想經過跨域手段操做它基本上是不可能的。javascript

document.domain

document.domain是比較經常使用的跨域方法。實現最簡單但只能用於同一個主域下不一樣子域之間的跨域請求,好比 foo.comimg.foo.com 之間,img1.foo.comimg2.foo.com 之間。只要把兩個頁面的document.domain都指向主域就能夠了,好比document.domain='foo.com';
設置好後父頁面和子頁面就能夠像同一個域下兩個頁面之間訪問了。父頁面經過ifr.contentWindow就能夠訪問子頁面的window,子頁面經過parent.windowparent訪問父頁面的window,接下來能夠進一步獲取dom和js。html

<!-- foo.com/a.html -->
<iframe id="ifr" src="http://img.foo.com/b.html"></iframe>
<script>
document.domain = 'foo.com';
function aa(str) {
    console.log(str);
}
window.onload = function () {
    document.querySelector('#ifr').contentWindow.bb('aaa');
}
</script>
<!-- img.foo.com/b.html -->
<script>
document.domain = 'foo.com';
function bb(str) {
    console.log(str);
}

parent.aa('bbb');
</script>

window.name

只要不關閉瀏覽器,window.name能夠在不一樣頁面加載後依然保持。嘗試在瀏覽器打開百度baidu.com,而後在控制檯輸入window.name='aaa';回車,接着在地址欄輸入qq.com轉到騰訊首頁,打開控制檯輸入window.name查看它的值,能夠看到輸出了"aaa"
例如子頁面bar.com/b.html向父頁面foo.com/a.html傳數據。java

<!-- foo.com/a.html -->
<iframe id="ifr" src="http://bar.com/b.html"></iframe>
<script>
function callback(data) {
    console.log(data)
}
</script>
<!-- bar.com/b.html -->
<input id="txt" type="text">
<input type="button" value="發送" onclick="send();">
<script>
var proxyA = 'http://foo.com/aa.html';    // foo.com下代理頁面
var proxyB = 'http://bar.com/bb.html';    // bar.com下代理空頁面

var ifr = document.createElement('iframe');
ifr.style.display = 'none';
document.body.appendChild(ifr);

function send() {
    ifr.src = proxyB;
}

ifr.onload = function() {
    ifr.contentWindow.name = document.querySelector('#txt').value;
    ifr.src = proxyA;
}
</script>
<!-- foo.com/aa.html -->
top.callback(window.name)

location.hash

較經常使用,把傳遞的數據依附在url上
例如獲取子頁面bar.com/b.html的高度及其餘數據webpack

<!-- foo.com/a.html -->
<iframe id="ifr" src="http://bar.com/b.html"></iframe>
<script>
function callback(data) {
    console.log(data)
}
</script>
<!-- bar.com/b.html -->
window.onload = function() {
    var ifr = document.createElement('iframe');
    ifr.style.display = 'none';
    var height = document.documentElement.scrollHeight;
    var data = '{"h":'+ height+', "json": {"a":1,"b":2}}';
    ifr.src = 'http://foo.com/aa.html#' + data;
    document.body.appendChild(ifr);
}
<!-- foo.com/aa.html -->
var data = JSON.parse(location.hash.substr(1));
top.document.getElementById('ifr').style.height = data.h + 'px';
top.callback(data);

window.navigator

IE6的bug,父頁面和子頁面均可以訪問window.navigator這個對象,在navigator上添加屬性或方法能夠共享。由於如今沒有IE6環境,這裏就不寫例子了。nginx

postMessage

HTML5新增方法,如今瀏覽器及IE8+支持,簡單易用高大上。web

.postMessage(message, targetOrigin)參數說明json

message: 是要發送的消息,類型爲 String、Object (IE八、9 不支持)
targetOrigin: 是限定消息接收範圍,不限制請使用 '*'

'message', function(e)回調函數第一個參數接收 Event 對象,有三個經常使用屬性:segmentfault

data: 消息
origin: 消息來源地址
source: 源 DOMWindow 對象

一個簡單的父頁面foo.com/a.html 和子頁面 bar.com/b.html創建通訊跨域

<!-- foo.com/a.html -->
<iframe id="ifr" src="http://bar.com/b.html"></iframe>
<script>
window.onload = function () {
    var ifr = document.querySelector('#ifr');
    ifr.contentWindow.postMessage({a: 1}, '*');
}
window.addEventListener('message', function(e) {
    console.log('bar say: '+e.data);
}, false);
</script>
<!-- bar.com/b.html -->
window.addEventListener('message', function(e){
    console.log('foo say: ' + e.data.a);
    e.source.postMessage('get', '*');
}, false)
相關文章
相關標籤/搜索