Когда VueJS не может помочь вам

Если вы хотите создать веб-страницу с помощью JavaScript, VueJS поможет вам и выполнит грязную работу за вас. Но есть условие: он работает только на тех блоках страницы, в которых он имеет единоличный контроль. Любая часть, которая может быть помешана другими скриптами или плагинами уже не для Vue.

Это значит, что теги head и body являются зонами без Vue. То есть если вы хотите управлять классом тега body напрямую например, то у вас ничего не получится.

Так как Vue не может управлять тегами head и body напрямую, он все равно поможет вам управлять ими другими способами.

 

Почему Vue придирчив к тому, где он работает?

Vue оптимизирует рендеринг страницы с помощью виртуального DOM. Это JavaScript-представление «реального» DOM, которое Vue хранит в памяти. Обновление DOM часто бывают медленным, поэтому сначала изменения происходят в виртуальном DOM, затем он обновляет реальный DOM, так Vue собственно и оптимизирует процесс.

Эта система будет сломана, если какая-либо третья сторона внесет изменения в DOM без ведома Vue, вызывая несоответствие между реальным DOM и виртуальным DOM.

По этой причине Vue не пытается контролировать всю страницу, а только ее часть, где будет иметь единоличный контроль.

 

Связывание с элементом

Первое, что мы обычно делаем в проекте Vue — это связываем селектор в объекте Vue через свойство el:

Тем самым говорим Vue, с какой частью страницы мы будем работать. Vue будет работать со связанным элементом, а также со всеми дочерними элементами. Но он не может воздействовать на элементы, находящиеся вне связанного элемента, будь то одноуровневые или же родительские элементы:

 

Нет привязки к body

Наверное вы склонны думать, что тег body будет лучшим местом для привязки, так как существует много причин для получения контроля над классами body, событиями body и т.д.

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

Это настоящий ужас для Vue, поэтому тег body находится за чертой ограничения. Фактически, начиная с версии 2, если вы попытаетесь сделать привязку к body или head, вы получите следующее предупреждение:

 

Управление тегами head и body

Итак, теперь, когда мы установили, что Vue должен привязываться к своему «личному» элементу внутри body, и он не может влиять на какую-либо часть DOM над этим элементом привязки, как вы сможете управлять body или head с Vue?

Ответ: вы не можете. Ну не напрямую, по крайней мере. Все, что находится вне привязанного элемента, фактически невидимо для Vue.

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

 

Сценарий №1: Прослушивание пользовательского ввода

Предположим, вы создаете модальное окно с Vue, и вы хотите, чтобы пользователь мог закрыть окно с помощью клавиши escape.

Vue дает вам директиву v-on для прослушивания событий, но если форма ввода находится не в фокусе во время нажатий, то ключевые события отправляются из тега body:

Поскольку body не находится в юрисдикции Vue, вы не сможете заставить Vue прослушать это событие. Вам нужно будет настроить собственный прослушиватель событий с помощью Web API:

 

Как Vue может помочь

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

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

 

Сценарий №2: Управление классами body

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

Чтобы убрать прокрутку, добавьте класс в body (назовем его modal-open), со свойством overflow: hidden.

Очевидно, нам нужно динамически добавлять и удалять этот класс, поскольку мы все равно хотим разрешить прокрутку, когда модальное окно закрыто. Обычно мы используем v-bind: class для выполнения этой задачи, но опять же, вы не можете привязываться к атрибутам body с помощью Vue, поэтому нам придется снова использовать Web API:

 

Как Vue может помочь

Vue добавляет реактивные геттеры и сеттеры к каждому элементу DOM, так что, когда изменяется значение данных, он обновляет DOM. Vue позволяет писать пользовательскую логику, которая перехватывает изменения реактивных данных через наблюдатель watch.

Vue будет выполнять любые колбэки наблюдателя всякий раз, когда изменяется значение данных (в данном случае modalOpen). Мы будем использовать этот колбэк, чтобы добавить или удалить класс body:

Не совсем точный перевод статьи на vuejsdevelopers.com