Как работать с локальными событиями IE11, которые срабатывают дважды или вообще не работают в iframe? - программирование
Подтвердить что ты не робот

Как работать с локальными событиями IE11, которые срабатывают дважды или вообще не работают в iframe?

Я предполагаю, что это ошибка, но я не смог найти об этом никаких обсуждений.

Известно, что IE10 будет (против spec) событий пожарной памяти локально (т.е. в том же глобальном контексте выполнения, из которого было вызвано событие), но IE11, похоже, еще больше отклоняется от спецификации (http://www.w3.org/TR/webstorage/), когда речь идет о iframe того же домена:

  • если iframe встроен в страницу, вызвавшую событие хранения, событие запустит TWICE в этом iframe.
  • Если iframe встроен в страницу, отличную от той, которая вызвала событие хранения, событие не будет срабатывать вообще внутри этого iframe.
  • Если событие запускается из iframe, оно будет срабатывать TWICE локально и TWICE в любом другом iframe, встроенном в ту же страницу, но совсем не в iframe других страниц.

Вы можете проверить это, открыв следующую ссылку на двух отдельных вкладках: http://hansifer.com/main.html

У кого-нибудь есть понимание этого причудливости?

Последняя проверенная версия: IE v11.0.9600.16476 (обновление 2016-08-13: по-видимому, это "обновленная версия", которая имеет значение, а не "Версия", как указано в диалоговом окне "О программе" )

Ссылка на отчет об ошибке: https://connect.microsoft.com/IE/feedback/details/811546/ie11-localstorage-events-fire-twice-or-not-at-all-in-iframes

ОБНОВЛЕНИЕ 2015-10-26

Я только заметил, что это, по-видимому, исправлено в версии 11.9.9600.18059, хотя я не могу сказать, когда исправление было сброшено, поскольку оно, похоже, не упоминается ни в одном недавнем КБ.

К сожалению, события локального хранилища IE11 по-прежнему являются аберрантными по-другому (хотя это отдельные говядины из проблемы, изложенной в этом сообщении):

  • IE вызывает события localStorage в контексте окна, из которого был вызван набор или удаление localStorage, вызвавшее событие. localStorage события должны быть подняты только в контексте внешнего окна того же происхождения. (обновление: работа в EdgeHTML 13.10586)

  • IE использует пустую строку вместо null для e.oldValue/e.newValue, когда элементы хранения добавляются/удаляются. (обновление: все еще проблема в EdgeHTML 13.10586)

  • IE вызывает обработчик события localStorage недетерминированно либо до начала, либо после установки/удаления вступает в силу вместо последовательно ПОСЛЕ.

ОБНОВЛЕНИЕ 2015-12-24

Похоже, что эта ошибка была перенесена на Edge (протестировано EdgeHTML 13.10586)

ОБНОВЛЕНИЕ 2016-02-02

Вельп, неважно. Эта ошибка снова наблюдается в IE v11.63.10586.0 (обновление 2016-08-13: по-видимому, это "обновленная версия", которая имеет значение, а не "Версия", как указано в диалоговом окне "О программе" )

ОБНОВЛЕНИЕ 2016-08-13

Теперь это исправлено в IE (Update Version 11.0.34), хотя события хранения все еще запущены в исходном окне, против spec (известный давний вопрос, как упоминалось выше).

Я нашел этот KB, который был включен в IE 14 июня, 2016 "Обновление безопасности" , хотя в соответствии с его описанием он обращается только ко второй марке.

Что касается Edge (проверено EdgeHTML 14.14393), похоже, что эта проблема теперь исправлена, но есть новая проблема: события хранения не запускаются в кадрах одинакового происхождения той же страницы.

Я сообщил об этом отдельно для MS здесь.

4b9b3361

Ответ 1

Если вы когда-либо хотите отключить событие от вызова несколько раз, независимо от причины вызова, используйте флаг для блокировки последующих событий. Существует несколько стратегий:

0,1. основанный на времени дросселирование. предположим, что у вас есть функция func, и вы хотите, чтобы ее вызывали только один раз за 200 мсек:

function func(){
  if (document.func_lock) return;
  document.func_lock=true; // block future calls
  setTimeout(function(){document.func_lock=null;},300);
}

При одновременном запуске нескольких событий вы можете ожидать, что все они попадут в окно 300 мс. Вышеприведенный код можно упростить, воспользовавшись дескриптором таймера:

function func(){
  if (document.func_lock) return;
  document.func_lock=setTimeout(function(){return;},300);
}

Когда таймер истекает, блокировка автоматически удаляется.

0,2. Удалите флаг с помощью обратного вызова. Процесс тривиальный, поэтому я не буду размещать здесь образец кода.

В терминах размещения флага вы можете использовать любой уникальный объект DOM. Поскольку я не знаю контекста вашего приложения, я просто использую "документ" здесь. Вы также можете использовать хеш-ключи, которые относятся к вашему приложению, поскольку вы уже имеете дело с локальным хранилищем. Концепция одинаков.

Ответ 2

Мне удалось обойти проблему, используя window.parent, чтобы зарегистрировать событие в iframe следующим образом:

Страница iframe

var win = window.parent || window.opener || window;
win.addEventListener('storage', handleLocalStorageEvent, false);

function handleLocalStorageEvent(e) {
    console.log('IFRAME local storage event', e);

    var sdf = document.getElementById('sdf');
    sdf.innerHTML = sdf.innerHTML + 'Storage Event => (' + e.newValue + ')<br>';
}

Отказ от ответственности: Обратите внимание, что это решение предназначено для устранения проблемы (IE7). Каким-либо образом предполагается или предлагается, чтобы это применимо ко всем браузерам.