首頁>Program>source

我正試圖做一个琐碎的 postMessage 示例工作...

  • in IE10
  • between windows/tabs (vs. iframes)
  • across origins

删除這些條件中的任何一个,一切正常:-)

但是据我所知,視窗之間是 postMessage 当两个視窗共享一个原點時,仅在IE10中工作. (實際上,而且很奇怪,這種行為比這更宽松:共享一个host的两个不同来源似乎也起作用)。

這是有記錄的錯誤吗? 有任何解決方法或其他建議吗?

(註意:這个問题解決了這些問题,但是其答案關於IE8和IE9,而不是10)


更多详细資訊+示例...

啟動頁面演​​示
<!DOCTYPE html>
<html>
  <script>
    window.addEventListener("message", function(e){
      console.log("Received message: ", e);
    }, false);
  </script>
  <button onclick="window.open('http://jsbin.com/ameguj/1');">
    Open new window
  </button>
</html>
啟動頁面演​​示
<!DOCTYPE html>
<html>
  <script>
    window.opener.postMessage("Ahoy!", "*");
  </script>
</html>

這適用於:http://jsbin.com/ahuzir/1-因為两个頁面都位於同一頁面 来源(jsbin.com).但是將第二頁移動到其他位置,則在IE10中失败。

最新回復
  • 5月前
    1 #

    I was mistaken when I originally posted this answer: it doesn't actually work in IE10. 顯然,人们出於其他原因發現此功能很有用,因此我將其留给後代使用.原始答案如下:


    值得一提的是:您在该答案中的鏈接已鏈接到 postMessage 並非针對IE8和IE9中的單独視窗是跨源的-但是,它也是在IE10出現之前於2009年編寫的.因此,我不会將其表示為已在IE10中修複。

    關於 postMessage 本身,http://caniuse.com/#feat=x-doc-messaging尤其表明它在IE10中仍然存在問题,這似乎与您的演示相匹配. Caniuse頁面鏈接到本文,其中包含一个非常相關的引用:

    Internet Explorer 8+ partially supports cross-document messaging: it currently works with iframes, but not new windows. Internet Explorer 10, however, will support MessageChannel. Firefox currently supports cross-document messaging, but not MessageChannel.

    因此,您最好的選擇是拥有一个 MessageChannel 基於代碼路徑,並迴退到 postMessage 如果不存在.它不会获得IE8 / IE9的支援,但至少可以与IE10一起使用。

    關於 MessageChannel的文件 :http://msdn.microsoft.com/zh-cn/library/windows/apps/hh441303.aspx

  • 5月前
    2 #

    在与啟動器相同的主機上建立代理頁面.代理頁面有一个 iframe 源設置為遠端頁面.跨域postMessage現在將在IE10中像這樣執行:

      Remote page uses window.parent.postMessage 將資料傳遞到代理頁面.由於它使用iframe,因此受IE10的支援

      代理頁面使用 window.opener.postMessage 將資料傳遞迴啟動器頁面.由於這是同一个域,因此没有跨域問题.如果您不想使用postMessage-例如,它也可以在啟動器頁面上直接呼叫全域性方法. window.opener.someMethod(data)


      示例(所有網址均為虛構)

      Launcher page at http://example.com/launcher.htm

      <!DOCTYPE html>
      <html>
          <head>
              <title>Test launcher page</title>
              <link rel="stylesheet" href="/css/style.css" />
          </head>
          <body>
          <script>
              function log(msg) {
                  if (!msg) return;
                  var logger = document.getElementById('logger');
                  logger.value += msg + '\r\n';
              }            
              function toJson(obj) {
                  return JSON.stringify(obj, null, 2);
              }
              function openProxy() {
                  var url = 'proxy.htm';
                  window.open(url, 'wdwProxy', 'location=no');
                  log('Open proxy: ' + url);
              }
              window.addEventListener('message', function(e) {
                  log('Received message: ' + toJson(e.data));
              }, false);
          </script>
          <button onclick="openProxy();">Open remote</button> <br/>
          <textarea cols="150" rows="20" id="logger"></textarea>
          </body>
      </html>
      

      Proxy page at http://example.com/proxy.htm

      <!DOCTYPE html>
      <html>
          <head>
              <title>Proxy page</title>
              <link rel="stylesheet" href="/css/style.css" />
          </head>
          <body>
          <script>
              function toJson(obj) {
                  return JSON.stringify(obj, null, 2);
              }
              window.addEventListener('message', function(e) {
                  console.log('Received message: ' + toJson(e.data));
                  window.opener.postMessage(e.data, '*');
                  window.close(self);
              }, false);
          </script>
          <iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe>
          </body>
      </html>
      

      Remote page at http://example.net/remote.htm

      <!DOCTYPE html>
      <html>
          <head>
              <title>Remote page</title>
              <link rel="stylesheet" href="/css/style.css" />
          </head>
          <body>
          <script>
              function remoteSubmit() {
                  var data = {
                      message: document.getElementById('msg').value
                  };
                  window.parent.postMessage(data, '*');
              }
          </script>
          <h2>Remote page</h2>
          <input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button>
          </body>
      </html>
      

  • 5月前
    3 #

    基於缠結的答案,我使用以下代碼段在IE11中成功[並模擬了IE10模式]:

    var submitWindow = window.open("/", "processingWindow");
    submitWindow.location.href = 'about:blank';
    submitWindow.location.href = 'remotePage to comunicate with';
    

    然後,我能够使用典型的postMessage堆棧进行通訊,在我的场景中使用了一个全域性靜態Messenger(尽管我不认為這有任何意義,我還附加了Messenger類)

    var messagingProvider = {
        _initialized: false,
        _currentHandler: null,
        _init: function () {
            var self = this;
            this._initialized = true;
            var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
            var eventer = window[eventMethod];
            var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
            eventer(messageEvent, function (e) {
                var callback = self._currentHandler;
                if (callback != null) {
                    var key = e.message ? "message" : "data";
                    var data = e[key];
                    callback(data);
                }
            }, false);
        },
        post: function (target, message) {
            target.postMessage(message, '*');
        },
        setListener: function (callback) {
            if (!this._initialized) {
                this._init();
            }
            this._currentHandler = callback;
        }
    }
    

    無論我多麼努力,我都無法在IE9和IE8上正常工作

    我的配置在哪裏工作:
    IE版本:11.0.10240.16590,更新版本:11.0.25(KB3100773)

  • 5月前
    4 #

    基於LyphTEC和Akrikos的答案,另一个解決方法是建立一个 <iframe> 在空白的弹出視窗中,這避免了單独的代理頁面的需要,因為空白的弹出視窗与其打開程式的起源相同。

    Launcher page at http://example.com/launcher.htm

    <html>
      <head>
        <title>postMessage launcher</title>
        <script>
          function openWnd() {
            var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"),
                i = w.document.createElement("iframe");
            i.src = "http://example.net/remote.htm";
            w.document.body.appendChild(i);
            w.addEventListener("message", function (e) {
              console.log("message from " + e.origin + ": " + e.data);
              // Send a message back to the source
              e.source.postMessage("reply", e.origin);
            });
          }
        </script>
      </head>
      <body>
        <h2>postMessage launcher</h2>
        <p><a href="javascript:openWnd();">click me</a></p>
      </body>
    </html>
    

    Remote page at http://example.net/remote.htm

    <html>
      <head>
        <title>postMessage remote</title>
        <script>
          window.addEventListener("message", function (e) {
            alert("message from " + e.origin + ": " + e.data);
          });
          // Send a message to the parent window every 5 seconds
          setInterval(function () {
            window.parent.postMessage("hello", "*");
          }, 5000);
        </script>
      </head>
      <body>
        <h2>postMessage remote</h2>
      </body>
    </html>
    

    我不確定這有多脆弱,但是它可以在IE 11和Firefox 40.0.3中正常工作。

  • 5月前
    5 #

    現在(2014-09-02),最好的選擇是 使用msdn博客文章中提到的代理框架,该框架详细說明了此問题的解決方法:https://blogs.msdn.microsoft.com/ieinternals/2009/09/15/html5-implementation-issues-in-ie8-and -後来/

    這是工作示例:http://www.debugtheweb.com/test/xdm/origin/

    您需要在頁面上設置与弹出視窗具有相同来源的代理框架.使用 window.opener.frames[0]將資訊从弹出視窗發送到代理框架 .然後从代理框架到主頁使用postMessage。

  • iphone:如何在iOS中的小鍵盤上添加"完成"按钮
  • ios:presentViewController:animated:yES视圖將不会出現,直到使用者再次轻按