📜  iframe 消息传递 - Html (1)

📅  最后修改于: 2023-12-03 15:31:22.062000             🧑  作者: Mango

iframe 消息传递 - Html

在网页开发中,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进行消息传递的常用方法。同时,我们也了解到了同源策略的限制以及如何跨域进行消息传递。需要根据具体的情况选择合适的技术方案,从而实现有效的消息传递。