window.self:
当前窗口自身的引用
window.parent:
上一级父窗口的引用
window.top:
最顶层窗口的引用
当页面中不存在 iframe
嵌套时,则三者均是当前窗口自身的引用。
子页面调用父页面方法:window.parent.fatherFn();
父页面调用子页面方法: window.sonFrameName.sonFn();
(sonFrameName
是iframe
的name
值)
//父页面
<button class="b" id="b">点击button>
<iframe src="a.html" name='child' id="f">iframe>
<script>
var ob=document.getElementById('b');
var msg='hellow,i'm your father!!'
ob.onclick=function(){
if(child.document.readyState=="complete"){
child.window.fnChild(msg); //关键
}
}
script>
//子页面
<script>
function fnChild (arg) {
console.log(arg); //确实得到了 hellow,i'm your father!!
}
script>
父页面调用子页面使用 childFrameName.window.fnName();
当然有一点很重要,你需要判断iframe 里面的东西是否加载完成,如果加载未完成就调用的话是会报错的;
判断iframe 加载是否完成有2种方法
childFrameName.document.readyState=="complete"
来判断;childFrameName.onload=function(){}
使用onload 回调函数,把调用的方法都写在这个回调函数里面;//在父页面
<div id="a" class="a">div>
<iframe src="a.html" name='child' id="f">iframe>
<script>
function changeColor(){
var oDiv=document.getElementById('a');
oDiv.style.backgroundColor="red";
}
script>
//在子页面
<button class="ob" onclick="c()">anniubutton>
<script>
function c(){
parent.window.changeColor(); //关键
}
script>
同样的,在子页面调用父页面的方法使用 parent.window.fnName()
就可以了;
这种操作难免会遇到父页面获取子页面的元素,或者子页面获取父页面的元素进行操作;
首先,我们有几种方法拿到子页面的window对象或者doucument 对象,(还是使用上面的html)
//原生js 获取子页面window对象
var childWindow = document.getElementById("f").contentWindow;
var childWindow = document.getElementsByTagName('f')[0].contentWindow;
//其实也就是普通的获取方法,只是后面多了一个contentWindow;
//jquery
var childWindow = $('#f').contentWindow;
//获取子页面的document对象 (假设已经通过上面的方法得到了window对象)
var frameDoc = childWindow.document;
var frameBody = frameDoc.body;
//jquery 也是跟上面的一样
var frameDoc = $(childWindow.document);
//原生获取元素
childWindow.document.getElementById('a') //上面都已经拿到了子页面的window对象,所以获取子页面的元素也就只需要想普通操作那样获取就好
childWindow.document.getElementById('a').style.color='red' //改个颜色
//jq拿子页面元素
$('#f').contents().find('#a'); //$('#f').contents 这相当于拿到了iframe 里面所有的dom;
//原生js
window.parent.document.getElementById('a'); //window.parent获取到父页面的window对象,那么接可以使用一般操作获取元素
window.parent.document.getElementById('a').style.color="red";//dom操作
//jquery
$("#a",parent.document); //$(父页面元素选择器, parent.document);
$("#a",parent.document).css('border','1px solid red');
上面的是不存在跨域的情况,但是有时候会遇到跨域情况,在这次的项目里面就是出于跨域状态下,开始看了一些资料,说是在用一个iframe做中间层去做,但是太麻烦,在这里介绍一个十分还用的方法postMessage
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
postMessage
十分强大,既可以子传父,也可以父穿子,并且可以突破同源限制
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,写的是你要通信的window对象。
例如:在iframe中向父窗口传递数据时,可以写成window.parent.postMessage()
,window.parent
表示父窗口。
message
需要传递的数据,字符串或者对象都可以。
targetOrigin
表示目标窗口的源,协议+域名+端口号,如果设置为“*”,则表示可以传递给任意窗口。在发送消息的时候,如果目标窗口的协议、域名或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。例如:
`window.parent.postMessage(‘hello world’,‘http://xxx.com:8080/index.html’)
只有父窗口是http://xxx.com:8080时才会接受到传递的消息。
[transfer]
可选参数。是一串和message 同时传递的 Transferable 对象,这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。我们一般很少用到。
需要监听的事件名为message
window.addEventListener('message', function (e) {
console.log(e.data) // e.data为传递过来的数据
console.log(e.origin) // e.origin为调用 postMessage 时消息发送方窗口的 origin(域名、协议和端口)
console.log(e.source) // e.source为对发送消息的窗口对象的引用,可以使用此来在具有不同origin的两个窗口之间建立双向通信
})
示例功能:跨域情况下,子父页面互发信息并接收。
<body>
<button onClick="sendInfo()">向子窗口发送消息button>
<iframe id="sonIframe" src="http://192.168.2.235/son.html">iframe>
<script type="text/javascript">
var info = {
message: "Hello Son!"
};
//发送跨域信息
function sendInfo(){
var sonIframe= document.getElementById("sonIframe");
sonIframe.contentWindow.postMessage(info, '*');
}
//接收跨域信息
window.addEventListener('message', function(e){
alert(e.data.message);
}, false);
script>
body>
<body>
<button onClick="sendInfo()">向父窗口发送消息button>
<script type="text/javascript">
var info = {
message: "Hello Parent!"
};
//发送跨域信息
function sendInfo(){
window.parent.postMessage(info, '*');
}
//接收跨域信息
window.addEventListener('message', function(e){
alert(e.data.message);
}, false);
script>
body>
注意:一定是页面加载完成后再发送消息,否则会因为 iframe 未加载完成报错。
Failed to execute ‘postMessage’ on ‘DOMWindow’
var iframe = document.createElement("iframe");
iframe.src = "http://www.baidu.com/";
if (!/*@cc_on!@*/0) { // if not IE
iframe.onload = function(){
alert("框架加载完毕.");
};
} else {
iframe.onreadystatechange = function(){
if (iframe.readyState == "complete"){
alert("框架加载完毕.");
}
};
}
document.body.appendChild(iframe);
//方法二
var iframe = document.createElement("iframe");
iframe.src = "http://www.baidu.com/";
if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
alert("Local iframe is now loaded.");
});
} else {
iframe.onload = function(){
alert("Local iframe is now loaded.");
};
}
document.body.appendChild(iframe);