📅  最后修改于: 2023-12-03 15:31:22.062000             🧑  作者: Mango
在网页开发中,iframe(内嵌框架)是一种十分常见的标签,它可以将一个网页嵌入到另一个网页中。但是在嵌入的页面中,有时会需要向外界的页面传递消息,这时就需要通过一些技巧来实现了。
在HTML中,可以通过iframe的contentWindow
属性来获取到内嵌页的window对象,从而实现对内嵌页的操作。但是由于iframe内嵌页和外部页的同源策略限制,这种方式往往只能在同域名下使用。
如果内嵌页和外部页是同源的,可以通过window.postMessage方法来实现跨文档的通信。postMessage可以向目标窗口发送一个消息,同时可以将一些数据传递过去,接收方可以通过监听window对象的message事件来获取到消息和数据。
下面是一个简单的示例代码:
<!-- 外部页面 -->
<iframe src="http://example.com/innerPage" id="myIframe"></iframe>
<script>
// 获取iframe内部窗口对象
var iframe = document.getElementById("myIframe");
var innerWindow = iframe.contentWindow;
// 发送消息到内部页
innerWindow.postMessage("hello, inner page", "http://example.com");
// 处理内部页发回的消息
window.addEventListener("message", function(e) {
if (e.origin === "http://example.com") {
console.log("received message:", e.data);
}
});
</script>
<!-- 内部页面 -->
<script>
// 处理来自外部页的消息
window.addEventListener("message", function(e) {
if (e.origin === "http://example.com") {
console.log("received message:", e.data);
// 发送消息回外部页
e.source.postMessage("hello, outer page", e.origin);
}
});
</script>
在上面的代码中,外部页面通过postMessage方法向内部页发送了一条消息,而内部页通过监听message事件来接收并处理这条消息,并发回了一条回复消息。
如果内嵌页和外部页不在同一个域名下,就不能直接使用window.postMessage进行消息传递了,因为这是被同源策略所限制的。但是可以通过一些额外的手段来实现跨域消息传递,这里介绍两种常用的方法:
页面跳转是一种比较简单的方式,它的原理是利用URL传递信息,将消息和数据打包在URL中,在内部页面中解析URL并将数据传递到父页面中。
下面是一个简单的示例代码:
<!-- 外部页面 -->
<iframe src="http://example.com/innerPage" id="myIframe"></iframe>
<script>
// 获取iframe内部窗口对象
var iframe = document.getElementById("myIframe");
var innerWindow = iframe.contentWindow;
// 发送消息到内部页
innerWindow.location.href = "http://example.com/innerPage#hello";
</script>
<!-- 内部页面 -->
<script>
// 处理来自外部页的消息
if (location.hash === "#hello") {
console.log("received message: hello");
// 发送消息回外部页
location.href = "http://example.com/#world";
}
</script>
在上面的代码中,外部页面通过修改内部页面的location.href来实现消息传递,内部页面则通过解析location.hash来接收传递的消息,并通过修改自身的location.href来回应消息。
第三方服务是一种比较复杂的方式,它的原理是通过一个中间服务器来实现跨域消息传递,将消息和数据通过中间服务器传递,达到跨域的效果。
下面是一个简单的示例代码:
<!-- 外部页面 -->
<iframe src="http://example.com/innerPage" id="myIframe"></iframe>
<script>
// 获取iframe内部窗口对象
var iframe = document.getElementById("myIframe");
var innerWindow = iframe.contentWindow;
// 发送消息到内部页
var xhr = new XMLHttpRequest();
var url = "http://example.com/proxy?url=" + encodeURIComponent("http://inner.example.com/");
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log("received message:", xhr.responseText);
}
};
xhr.send(JSON.stringify({
message: "hello"
}));
</script>
<!-- 内部页面 -->
<script>
// 处理来自外部页的消息
var xhr = new XMLHttpRequest();
var url = "http://example.com/proxy?url=" + encodeURIComponent("http://outer.example.com/");
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log("received message:", xhr.responseText);
// 发送消息回外部页
var xhr2 = new XMLHttpRequest();
var url2 = "http://example.com/proxy?url=" + encodeURIComponent("http://outer.example.com/");
xhr2.open("POST", url2);
xhr2.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr2.send(JSON.stringify({
message: "world"
}));
}
};
xhr.send(JSON.stringify({
message: "hello"
}));
</script>
在上面的代码中,外部页面通过向第三方服务器发送一条代理请求,中间服务器将请求转发到内部页面,并返回处理结果,内部页面接收请求并处理数据,然后再通过第三方服务器向外部页面发送一条代理请求,中间服务器将请求转发到外部页面。
需要注意的是,这种方式需要借助于一个中间服务器来实现,需要自行实现代理服务或者使用第三方的代理服务。
通过本文的介绍,我们了解了在Html中使用iframe进行消息传递的常用方法。同时,我们也了解到了同源策略的限制以及如何跨域进行消息传递。需要根据具体的情况选择合适的技术方案,从而实现有效的消息传递。