Почему событие resize постоянно срабатывает, когда я назначаю ему обработчик с таймаутом?

Я назначил тайм-аут своему обработчику window.resize, чтобы не вызывать мой код изменения размера значительного количества каждый раз, когда происходит событие resize. Мой код выглядит так:

<script>
function init() {
  var hasTimedOut = false;
  var resizeHandler = function() {
    // do stuff
    return false;
  };

  window.onresize = function() {
    if (hasTimedOut !== false) {
      clearTimeout(hasTimedOut);
    }
    hasTimedOut = setTimeout(resizeHandler, 100); // 100 milliseconds
  };
}
</script>
<body onload="init();">
...
etc...

В IE7 (и, возможно, в других версиях) кажется, что при этом событие resize будет постоянно запускаться. Точнее, он будет срабатывать после каждого тайм-аута - в этом случае 100 миллисекунд.

Есть идеи, почему или как остановить это поведение? Я действительно не хотел бы называть свой код изменения размера для каждого события изменения размера, которое запускается в одном изменении размера, но это хуже.

4 ответа

Решение

В своем коде //do stuff вы манипулируете какими-либо свойствами top,left,width,height,border,margin или padding?

Вы можете непреднамеренно запускать рекурсию, которая непреднамеренно вызывает рекурсию, которая непреднамеренно запускает рекурсию...

IE действительно постоянно запускает событие изменения размера во время изменения размера (что вы должны знать, поскольку вы уже реализуете таймаут для исправления).

Я могу воспроизвести результаты, которые вы видите, используя ваш код, на моей тестовой странице.

Однако проблема исчезнет, ​​если я увеличу время ожидания до 1000 вместо 100. Возможно, вы захотите попробовать другие значения ожидания, чтобы увидеть, что работает для вас.

Вот тестовая страница, которую я использовал: на ней уже настроен довольно динамичный период ожидания, чтобы вы могли с ним поиграть.

Как исправить событие изменения размера в IE

также см. ответ для "scunliffe" "В ваших... свойствах?

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

Контекст: у меня есть iframe-страница, загруженная внутри родительской страницы, и iframe должен уведомлять родителя об изменении его размера, чтобы родитель мог соответствующим образом изменить размер iframe, достигнув динамического изменения размера iframe.

Итак, в HTML-документе iframe я попытался зарегистрировать обратный вызов в теге body. Во-первых, на обмене - не получилось. Затем при изменении размера - это сработало, но постоянно стреляло. (Позже я нашел причину - видимо, это была ошибка в Firefox, который пытался расширить мою страницу до бесконечности). Пробовал ResizeObserver - безрезультатно, получилось то же самое.

Решение, которое я реализовал, было следующим:

      <body onload="docResizePipe()">
<script>
var v = 0;
const docResizeObserver = new ResizeObserver(() => {
    docResizePipe();
});
docResizeObserver.observe(document.querySelector("body"));
function docResizePipe() {
    v += 1;
    if (v > 5) {
        return;
    }
    var w = document.body.scrollWidth;
    var h = document.body.scrollHeight;
    window.parent.postMessage([w,h], "*");
}
setInterval(function() {
    v -= 1;
    if (v < 0) {
        v = 0;
    }
}, 300);
</script>

Итак, как это работает: каждый раз, когда срабатывает обратный вызов, мы увеличиваем переменную v; раз в каждые 300 мс мы уменьшаем его на единицу; если он слишком большой, стрельба блокируется.

Большое преимущество этого решения по сравнению с решением, основанным на тайм-ауте, заключается в том, что оно вводит задержку для взаимодействия с пользователем, а также ясно показывает, как именно оно блокирует рекурсию. (Вообще-то нет)))

Другие вопросы по тегам