Статьи

Представляем enquire.js

В течение некоторого времени я использовал библиотеку enquire.js для расширения использования медиа-запросов в JavaScript. У меня был большой успех при использовании библиотеки в различных проектах, но большинство разработчиков, с которыми я встречался, признались, что никогда не использовали и даже не слышали об этом.

В этой статье я хочу представить вам библиотеку, объяснить, почему и как вы хотите ее использовать.

Что такое enquire.js?

enquire.js — это легкая, чистая библиотека JavaScript для ответа на медиа-запросы CSS. По моим собственным словам, enquire.js дает вам дополнительную функциональность и гибкость поверх window.matchMedia() при работе с медиа-запросами в JavaScript.

Библиотека была написана Ником Уильямсом, и она существует уже около трех лет, имея большой объем деятельности с открытым исходным кодом . Его цель не состоит в том, чтобы заменить или заполнить matchMedia ; скорее, он существует для обеспечения дополнительной функциональности вокруг медиазапросов, которые не существуют изначально.

Зачем мне это использовать?

Существует множество вариантов использования enquire.js, в том числе:

  • Переместить узлы вокруг DOM
  • Загрузка дополнительного контента (например, рекламы) через Ajax
  • Загрузите и запустите библиотеку JavaScript (например, Packery ) для улучшения страницы

Каждый из этих вариантов использования рассматривается в следующих разделах.

DOM Manipulation

Хотя при использовании JavaScript для манипулирования DOM существуют некоторые соображения по поводу производительности и удобства обслуживания, существует множество причин, по которым это можно сделать.

Предположим, что в вашем блоге у вас есть биография с изображением на боковой панели. На маленьких экранах боковая панель скрыта — но вы все равно хотите, чтобы биография была видна в конце вашего поста. Вместо дублирования био (и изображения) разметки, вы можете перемещать ее по DOM в зависимости от размера экрана, избегая дублирования разметки. Вот пример:

 window.$ = document.querySelector.bind(document); enquire.register("screen and (max-width:40em)", { match: function() { $(".Post-content").appendChild($(".Bio")); }, unmatch: function() { $(".Sidebar").insertBefore($(".Bio"), $(".Sidebar").firstChild); } }); 

Демонстрационная версия этого примера показана ниже:

Это зачаточный пример, и, честно говоря, он не делает намного больше, чем предоставляет нативный matchMedia() . На самом деле, вот как вы можете сделать это с помощью matchMedia() :

 window.$ = document.querySelector.bind(document); (function() { var mq = window.matchMedia("(min-width:40em)"); mq.addListener(positionBio); function positionBio(mediaQuery) { if (mediaQuery.matches) { $(".Sidebar").insertBefore($(".Bio"), $(".Sidebar").firstChild); } else { $(".Post-content").appendChild($(".Bio")); } } // On load positionBio(mq); }()); 

Демонстрационная версия этого примера показана ниже:

Давайте вернемся к enquire.js и продолжим приведенный выше пример. В следующем коде мы будем использовать функцию setup . Это функция, которая запускается только один раз, как только enquire.register . В этом примере мы также кешируем несколько селекторов, чтобы улучшить производительность кода и сделать его более читаемым и обслуживаемым. Хотя это надуманный пример (и вы можете сделать то же самое без enquire.js), он позволяет мне познакомить вас с функцией setup и изучить более сложные примеры:

 window.$ = document.querySelector.bind(document); enquire.register("screen and (max-width:40em)", { setup: function() { this.bio = $(".Bio"); this.content = $(".Post-content"); this.sidebar = $(".Sidebar"); }, match: function() { this.content.appendChild(this.bio); }, unmatch: function() { this.sidebar.insertBefore(this.bio, this.sidebar.firstChild); } }); 

Демонстрационная версия этого примера показана ниже:

Дополнительный контент

Давайте сосредоточим наше внимание на другом случае использования: загрузка рекламного контента через Ajax в зависимости от размера области просмотра. В этом примере снова используется функция setup() и вводится еще одна функция enquire.js: deferSetup() . Он также использует библиотеку reqwest Ajax (здесь нет classList ) и API classList чтобы продемонстрировать, как можно написать более сложный пример без jQuery. Если вы не знаете, что делает этот API, вы можете прочитать статью Изучение API classList .

В следующем примере в методе setup (который напоминает вам, что он запускается только один раз, когда этот медиа-запрос совпадает) мы используем метод ad.html ajax() для запроса страницы ad.html и сохранения результата в свойстве ad . Затем мы устанавливаем содержимое .Ad для свойства и показываем контейнер, добавляя is-visible класс (обрабатывается с помощью CSS).

Если медиа-запрос когда-либо «не соответствует», мы удалим is-visible класс, который, в свою очередь, .Ad контейнер .Ad .

Наконец, мы будем использовать флаг deferSetup вместе с методом setup() чтобы Ajax-запрос deferSetup только один раз и только при deferSetup медиа-запроса. Это полезно, потому что вызов Ajax задерживается до момента, когда требуется информация, вместо того, чтобы делать преждевременный запрос.

Код, который реализует то, что я только что описал, представлен ниже:

 window.$ = document.querySelector.bind(document); enquire.register("screen and (min-width:40em)", { deferSetup: true, setup: function() { this.ad = ""; this.adContainer = $(".Ad"); this.visibleClass = "is-visible"; this.adUrl = "//codepen.io/damonbauer/pen/LVgxxN.html"; reqwest({ url: this.adUrl, crossOrigin: true}) .then(function(response) { this.ad = response; }.bind(this)).fail(function() { this.ad = "Ad could not be loaded."; }.bind(this)).always(function(response) { this.adContainer.innerHTML = this.ad; }.bind(this)); }, match: function() { this.adContainer.classList.add(this.visibleClass); }, unmatch: function() { this.adContainer.classList.remove(this.visibleClass); } }); 

В дополнение к предыдущему коду JavaScript мы также должны использовать небольшой фрагмент кода CSS, представленный ниже:

 .Ad { display: none; } .is-visible { display: block; } 

Демонстрационная версия этого примера показана ниже:

Улучшения страницы

В этом разделе мы рассмотрим добавление библиотеки Packery для улучшения страницы в больших размерах. Согласно его документации , Packery «заполняет пустые места». Это помогает вам выполнить что-то похожее на макет Pinterest, где карты заполняют доступное пространство в сетке.

Допустим, у вас есть следующий HTML-код на вашей странице:

 <div id="Container"> <div class="Item">...</div> <div class="Item">...</div> <div class="Item">...</div> ... </div> 

Следующий код будет использовать библиотеку пакетов для достижения того, что я ранее описал:

 enquire.register("screen and (min-width:30em)", { deferSetup: true, setup: function() { this.container = $( "#Container" ); }, match: function() { this.container.packery({ itemSelector: '.Item' }); }, unmatch: function() { this.container.packery('destroy'); } }); 

Демонстрационная версия этого примера показана ниже:

Это очень похоже на первый пример. Он начинается с сохранения контейнера как свойства в методе setup() . Затем, если медиа-запрос совпадает, он будет packery элементы в соответствии с соглашением о packery ; в противном случае мы уничтожаем экземпляр packery , вызывая его метод destroy .

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

Потенциальные болевые точки

Надеюсь, вы получили представление о том, насколько быстрым и мощным может быть enquire.js. Я хотел бы поделиться парой случаев, когда у меня возникали проблемы при использовании библиотеки.

Старые версии Internet Explorer

Хотя он не полностью поддерживает IE8, я могу вам сказать, что созданные мной сайты не содержат никаких ошибок рендеринга JavaScript. Enquire.js зависит от API matchMedia , который не поддерживается в версиях Internet Explorer до 10. Если вам требуется поддержка таких браузеров, я предлагаю вам использовать полифилы matchMedia, написанные Полом Айришем .

Для этого вам необходимо загрузить предоставленные файлы до enquire.js. Кроме того, я предлагаю вам поместить эти скрипты в условный комментарий IE, как показано ниже:

 <!--[if lte IE 9]> <script src="/path/to/matchMedia.js"></script> <script src="/path/to/matchMedia.addListener.js"></script> <![endif]--> 

Благодаря такому подходу их загружают только те браузеры, которым нужны полифилы. Важно подчеркнуть, что даже если вы загрузите их в браузеры, поддерживающие эти функции, у вас все равно будет собственная реализация, поскольку оба сценария написаны неинвазивным способом. Это означает, что перед выполнением любого кода они обнаруживают, поддерживает ли браузер эти функции. Если это так, то код полифилла вообще пропускается.

Управление DOM

В одном из приведенных выше примеров я показал, как использовать enquire.js для управления DOM. Хотя этот метод работает, я бы посоветовал использовать его осторожно. Остерегайтесь добавления множества изменений DOM в несколько методов enquire.js match и unmatch поскольку чем больше операций вы добавляете, тем сложнее будет отлаживать страницу, если что-то пойдет не так. Кроме того, поскольку манипулирование с DOM обычно медленное, использование этой техники может привести к потере страницы и снижению производительности.

Прогрессивный контент

Мое предложение состоит в том, чтобы использовать enquire.js для «постепенного» предоставления содержимого или функциональности, а не полагаться на него для отображения критических частей содержимого. Мой совет — сначала показывать основной контент, а затем улучшать его с помощью enquire.js, а не в зависимости от того, какой контент будет улучшен.

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

Mobile First

В наши дни это обычная и рекомендуемая практика для создания сайтов с использованием подхода, ориентированного на мобильные устройства. Если браузер, который вам требуется поддерживать, не понимает медиазапросы (например, IE8), enquire.js имеет параметр с именем shouldDegrade который пригодится. Он указывает, что результат блока enquire.register всегда должен выполняться, если браузер не понимает медиазапросы. По умолчанию это значение установлено на false но вы можете изменить его на true чтобы соответствовать вашим потребностям.

Пример использования этого параметра приведен ниже:

 enquire.register("screen and (min-width:40em)", function() { // execute some code for large-screen devices }, true); // note the true! 

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

Выводы

В этой статье я познакомил вас с enquire.js, мощной библиотекой, написанной на чистом JavaScript для ответа на медиа-запросы CSS. Надеюсь, я продемонстрировал вам, как он дает вам дополнительные функции в дополнение к встроенному matchMedia() позволяющему создавать эффективные, многофункциональные веб-сайты для всех размеров экрана. Хотя это не был исчерпывающий обзор библиотеки, этого должно быть достаточно, чтобы подтолкнуть вас к тому, чтобы узнать о ней больше и подумать, есть ли место для этого в ваших проектах.

Вы когда-нибудь слышали о enquire.js? Вы когда-нибудь пытались использовать его в своих проектах? Как насчет ваших результатов? Поделитесь своими комментариями ниже, и давайте начнем обсуждение!