頁面嵌套iframe是比較常見的,好比QQ相關業務頁面的登陸框通常都是iframe的。使用ifrmae跨域要知足一個基本條件,父頁面和子頁面都是本身能夠控制的,若是隨便把iframe指向一個其餘網站,想經過跨域手段操做它基本上是不可能的。javascript
document.domain
是比較經常使用的跨域方法。實現最簡單但只能用於同一個主域下不一樣子域之間的跨域請求,好比 foo.com 和 img.foo.com 之間,img1.foo.com 和 img2.foo.com 之間。只要把兩個頁面的document.domain
都指向主域就能夠了,好比document.domain='foo.com';
。
設置好後父頁面和子頁面就能夠像同一個域下兩個頁面之間訪問了。父頁面經過ifr.contentWindow
就能夠訪問子頁面的window,子頁面經過parent.window
或parent
訪問父頁面的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
能夠在不一樣頁面加載後依然保持。嘗試在瀏覽器打開百度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)
較經常使用,把傳遞的數據依附在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);
IE6的bug,父頁面和子頁面均可以訪問window.navigator
這個對象,在navigator
上添加屬性或方法能夠共享。由於如今沒有IE6環境,這裏就不寫例子了。nginx
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)