1.跨域的一个示例
当你需要操作一个内嵌iframe时,如果这个内嵌iframe和打开的网站不在同一个域中,你时常会遇到这样的报错:
Unsafe JavaScript attempt to access frame with URL http:/www.d1.com from frame with URL http://www.d2.com. Domains, protocols and ports must match.
从报错信息中我们可以知道,浏览器是通过域名(domain),协议(HTTP),端口(Port)。也就是说这三点只要有一个不匹配那就是跨域(Cross domain)。
对于跨域,我们通常的解决办法是在原来的域添加一个文件,用该文件作为中间人来实现跨域。也就是说,先发消息到该文件,由该文件再操作同域的HTML。
HTML 5给我们带来了安全的跨域通信接口,即window.postMessage()方法。它方法原型是:
window.postMessage(msg, domain);
我们可以给指定的domain发送msg。而接收msg的iframe只要注册一个监听事件就可以了。我们看示例:
www.d1.com/a.html
<html>
<head>
<title>operate the iframe on other domain</title>
<script>
function sendMessage(){
var frm = document.getElementByIdx_x_x("iframe1");
frm.contentWindow.postMessage("hello","*")
}
</script>
</head>
<body>
<input id="send" type="button" onclick="sendMessage()" value="send message" />
<br />
<iframe style="300px; height:400px;" id="iframe1" src="http://www.d2.com/b.html"></iframe>
</body>
</html>
我们再看看监听的那个iframe
www.d2.com/b.html
<html>
<head>
<title>a frame which receive the message</title>
<script>
var OnMessage = function (e) {
alert(e.data);
}
function init() {
if (window.addEventListener) { // all browsers except IE before version 9
window.addEventListener("message", OnMessage, false);
} else {
if (window.attachEvent) { // IE before version 9
window.attachEvent("onmessage", OnMessage);
}
}
}
init();
</script>
</head>
<body>
<p>a iframe to receive the message</p>
</body>
</html>
在监听处理函数中我们可以判断具体的那个domain发来的消息。
注意事项
如果你在接受消息的iframe中通过JavaScript来修改DOM元素。要确保iframe已经加载完成,可以这样做:
_overlay = document.getElementByIdx_x_x("iframe1");
if(_overlay.attachEvent){
_overlay.attachEvent("onreadystatechange", function(){
if(_overlay.readyState === "complete" || _overlay.readyState == "loaded"){
_overlay.detachEvent( "onreadystatechange", arguments.callee);
sendMessage();
}
});
} else {
if(_overlay.addEventListener){
_overlay.addEventListener( "load", function(){
this.removeEventListener( "load", arguments.call, false);
sendMessage();
}, false);
}
}
注意:子框架向父框架发送消息用
window.parent.postMessage({type: 'IndexBack'}, '*');
监听消息类似