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

Я пытаюсь адаптировать простой набор медиа-запросов от css к javascript. Определение css работает должным образом, а код javascript - нет.

Блоки кода выглядят следующим образом:

  window.matchMedia("(min-width: 401px) and (max-width: 600px)")
  .addListener( function() {
    console.info("CALLBACK (max-width: 600px)");
    document.body.style.background = "red";
  });

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

Я ожидал, что будет вызван только тот, который соответствует текущей ширине.

Например, когда я меняю размер браузера с window.innerWidth 1871 на window.innerWidth 700, происходит следующее:

window.innerWidth: 1871
CALLBACK (max-width: 800px)
CALLBACK (min-width: 801px)
window.innerWidth: 700

и применяется обратный вызов для min-width 801px.

Что я делаю неправильно?

Полный тестовый код находится здесь:

<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1">

<script>

window.onresize = afterWindowResize;
function afterWindowResize(){
  showSize();
}

function x(){
  showSize();

  window.matchMedia("(max-width: 400px)")
  .addListener( function() {
    console.info("CALLBACK (max-width: 400px)");
    document.body.style.background = "green";
  });

  window.matchMedia("(min-width: 401px) and (max-width: 600px)")
  .addListener( function() {
    console.info("CALLBACK (max-width: 600px)");
    document.body.style.background = "red";
  });

  window.matchMedia("(min-width: 601px) and (max-width: 800px)")
  .addListener( function() {
    console.info("CALLBACK (max-width: 800px)");
    document.body.style.background = "blue";
  });

  window.matchMedia("(min-width: 801px)")
  .addListener( function() {
    console.info("CALLBACK (min-width: 801px)");
    document.body.style.background = "gray";
  });
}

function showSize(){
  console.info("window.innerWidth: " + window.innerWidth); 
}

</script>
</head>
<body onload = "x()">
</body>
</html>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
205
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы пропустите событие, а затем используете matches, он будет работать правильно

window.matchMedia("...").addListener( function(e) {
    if (e.matches) {
       // do something
    }
}

Или вы также можете использовать this, например if (this.matches) {...}

Фрагмент стека

<!DOCTYPE html>
<html>

  <head>
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1">

    <script>
      window.onresize = afterWindowResize;

      function afterWindowResize() {
        showSize();
      }

      function x() {
        showSize();

        window.matchMedia("(max-width: 400px)")
          .addListener(function(e) {
            if (e.matches) {
              console.info("CALLBACK (max-width: 400px)");
              document.body.style.background = "green";
            }
          });

        window.matchMedia("(min-width: 401px) and (max-width: 600px)")
          .addListener(function(e) {
            if (e.matches) {
              console.info("CALLBACK (max-width: 600px)");
              document.body.style.background = "red";
            }
          });

        window.matchMedia("(min-width: 601px) and (max-width: 800px)")
          .addListener(function(e) {
            if (e.matches) {
              console.info("CALLBACK (max-width: 800px)");
              document.body.style.background = "blue";
            }
          });

        window.matchMedia("(min-width: 801px)")
          .addListener(function(e) {
            if (e.matches) {
              console.info("CALLBACK (min-width: 801px)");
              document.body.style.background = "gray";
            }
          });
      }

      function showSize() {
        console.info("window.innerWidth: " + window.innerWidth);
      }

    </script>
  </head>

  <body onload = "x()">
  </body>

</html>

Глупый я. Я неявно предполагал, что обратный вызов вызывается только при совпадении условия. Спасибо!

Nathan Perigreth 23.04.2018 17:53

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