Я пытаюсь заставить postMessage
работать тривиальный пример ...
- в IE10
- между окнами / вкладками (по сравнению с iframe)
- через происхождение
Удалите любое из этих условий, и все заработает :-)
Но, насколько я могу судить, между окнами работает postMessage
только IE10, когда оба окна имеют общий источник. (Что ж, на самом деле - и это странно - поведение немного более снисходительно, чем это: два разных происхождения, которые имеют общий хост, похоже, тоже работают).
Это задокументированная ошибка? Какие-нибудь обходные пути или другие советы?
(Примечание: этот вопрос касается проблем, но его ответ касается 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 она не удастся.
window.parent.postMessage
в IE.Ответы:
Я ошибся, когда изначально опубликовал этот ответ: на самом деле он не работает в IE10. Очевидно, люди сочли это полезным по другим причинам, поэтому я оставляю это для потомков. Оригинальный ответ ниже:
Стоит отметить: ссылка в этом ответе, которую вы связали с состояниями,
postMessage
не является перекрестным источником для отдельных окон в IE8 и IE9, однако она также была написана в 2009 году, до появления IE10. Поэтому я бы не стал считать это признаком того, что это исправлено в IE10.Что касается
postMessage
самого себя, http://caniuse.com/#feat=x-doc-messaging заметно указывает на то, что он все еще не работает в IE10, что, похоже, соответствует вашей демонстрации. На странице caniuse есть ссылка на эту статью , которая содержит очень актуальную цитату:Так что лучше всего, вероятно, иметь
MessageChannel
основанный кодовый путь и вернуться к нему,postMessage
если его не существует. Он не даст вам поддержки IE8 / IE9, но, по крайней мере, он будет работать с IE10.Документы на
MessageChannel
: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspxисточник
MessageChannel
работающий кодовый путь? Вам все еще нужно работать,postMessage
чтобы передать порт канала в другое окно.postMessage
с новымMessageChannel
API будет работать в новых окнах и источниках. Работа, наверное, немного неудобная, но в основном:postMessage('foo', '*')
плохая,postMessage('foo', [messageChannel.port2])
хорошая.Создайте прокси-страницу на том же хосте, что и панель запуска. Страница прокси имеет
iframe
источник, установленный на удаленную страницу. Сообщение postMessage с перекрестным происхождением теперь будет работать в IE10 следующим образом:window.parent.postMessage
для передачи данных на прокси-страницу. Поскольку здесь используются фреймы, он поддерживается IE10.window.opener.postMessage
для передачи данных обратно на страницу запуска. Поскольку это в том же домене - проблем с перекрестным происхождением нет. Он также может напрямую вызывать глобальные методы на странице запуска, если вы не хотите использовать postMessage - например.window.opener.someMethod(data)
Образец (все URL фиктивные)
Страница запуска на
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>
Страница прокси на
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>
Удаленная страница в
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>
источник
== РАБОЧЕЕ РЕШЕНИЕ В 2020 ГОДУ без iframe ==
Основываясь на ответе путаницей, я добился успеха в IE11 [и эмулировал режим IE10], используя следующий фрагмент:
var submitWindow = window.open("/", "processingWindow"); submitWindow.location.href = 'about:blank'; submitWindow.location.href = 'remotePage to comunicate with';
Затем я смог общаться, используя типичный стек postMessage, в моем сценарии я использую один глобальный статический мессенджер (хотя я не думаю, что это имеет какое-то значение, я также прикрепляю свой класс мессенджера)
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)
источник
Основываясь на ответах LyphTEC и Akrikos, еще одним решением является создание
<iframe>
пустого всплывающего окна, что позволяет избежать необходимости в отдельной прокси-странице, поскольку пустое всплывающее окно имеет то же происхождение, что и его открывающее средство.Страница запуска на
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>
Удаленная страница в
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.
источник
<iframe>
направления) в IE 11 (11.0.9600.18036
, версии обновления11.0.23 (KB3087038)
). Возможно, замешано последнее обновление безопасности ( KB3087038 ).Прямо сейчас (02.09.2014) лучше всего использовать фрейм прокси, как указано в сообщении блога msdn, в котором подробно описывается обходной путь для этой проблемы: https://blogs.msdn.microsoft.com/ieinternals/2009 / 09/15 / html5-implementation-issues-in-ie8-and-later /
Вот рабочий пример: http://www.debugtheweb.com/test/xdm/origin/
Вам необходимо настроить прокси-фрейм на своей странице, который имеет то же происхождение, что и всплывающее окно. Отправьте информацию из всплывающего окна в фрейм прокси, используя
window.opener.frames[0]
. Затем используйте postMessage из фрейма прокси на главную страницу.источник
Это решение включает добавление сайта в доверенные сайты Internet Explore, а не в сайты локальной интрасети. Я тестировал это решение в Windows 10 / IE 11.0.10240.16384, Windows 10 / Microsoft Edge 20.10240.16384.0 и Windows 7 SP1 / IE 10.0.9200.17148. Страница не должна быть включена в зону интрасети .
Итак, откройте конфигурацию Internet Explorer (Инструменты> Свойства обозревателя> Безопасность> Надежные сайты> Сайты) и добавьте страницу, здесь я использую *, чтобы сопоставить все поддомены. Убедитесь, что страницы нет в списке сайтов местной интрасети (Инструменты> Свойства обозревателя> Безопасность> Локальная интрасеть> Сайты> Дополнительно). Перезагрузите браузер и повторите попытку.
В Windows 10 / Microsoft Edge эту конфигурацию можно найти в Панели управления> Свойства обозревателя.
ОБНОВИТЬ
Если это не сработает, вы можете попробовать сбросить все свои настройки в Инструменты> Свойства обозревателя> Дополнительные настройки> Сбросить настройки Internet Explorer, а затем Сброс: используйте его с осторожностью. ! Затем вам нужно будет перезагрузить вашу систему. После этого добавьте сайты в Надежные сайты.
Посмотрите, в какой зоне находится ваша страница, в меню «Файл»> «Свойства» или щелкните правой кнопкой мыши.
ОБНОВИТЬ
Я нахожусь в корпоративной интрасети, и иногда это работает, а иногда нет (автоматическая настройка? Я даже начал обвинять корпоративный прокси). В итоге я использовал это решение https://stackoverflow.com/a/36630058/2692914 .
источник
Этот Q старый, но это то, для чего предназначен easyXDM, возможно, проверьте его как потенциальный запасной вариант, когда вы обнаружите браузер, который не поддерживает html5 .postMessage:
https://easyxdm.net/
Он использует оболочку VBObject и все типы вещей, с которыми вы никогда не захотите иметь дело, для отправки междоменных сообщений между окнами или фреймами, где window.postMessage не работает для различных версий IE (и, возможно, край, все еще не уверен на 100% в поддержке Edge имеет, но, похоже, также нуждается в обходном пути для .postMessage)
источник
MessageChannel не работает для IE 9-11 между окнами / вкладками, поскольку он полагается на postMessage, который все еще не работает в этом сценарии. «Лучший» обходной путь - вызвать функцию через window.opener (например, window.opener.somefunction («somedata»)).
Подробнее об обходном пути здесь
источник