Если вы хотите создать веб-страницу с помощью JavaScript, Vue.js может сделать на ней одну чертову работу. Но есть условие: он работает только в тех частях страницы, где он имеет беспрепятственный контроль. Любая часть, на которую могут повлиять другие скрипты или плагины, для Vue запрещена.
Это означает , что head
и body
теги Вью-свободные зоны. Это настоящий облом, если вы хотите, чтобы Вью руководил классом body
, чтобы привести один пример.
Но хотя Vue не может напрямую управлять тегами head
или body
, он все же может помочь вам управлять ими другими способами.
Говядина Vue с метками головы и тела
Почему Vue требователен к тому, где это работает?
Vue оптимизирует рендеринг страниц за счет использования виртуального DOM . Это JavaScript-представление «настоящего» DOM, которое Vue хранит в памяти. Обновления DOM часто происходят медленно, поэтому сначала вносятся изменения в виртуальный DOM, что позволяет Vue оптимизировать процесс обновления реального DOM с помощью пакетной обработки и т. Д.
Эта система будет подорвана, если какая-то третья сторона внесет изменения в DOM без ведома Vue, что приведет к несоответствию между реальным DOM и виртуальным DOM.
По этой причине Vue не будет пытаться контролировать всю страницу, а только часть страницы, где он знает, что он будет иметь беспрепятственный контроль.
Гора Элемент
Первое, что мы обычно делаем в проекте Vue, — это предоставляем Vue элемент монтирования в объекте конфигурации через el
свойство:
JavaScript
1
new Vue({
2
el: '#app'
3
});
Это говорит Vue, где мы отложили часть страницы, которую она может иметь для себя. Vue будет владычествовать над этим элементом и всеми его детьми. Но он не может повлиять ни на один элемент вне элемента монтирования, будь то родной брат или предок:
HTML
xxxxxxxxxx
1
<head>
2
<!--Vue has no power here!-->
3
</head>
4
<body>
5
<!--Vue has no power here!-->
6
<div id="app">
7
<!--Vue's dominion-->
8
</div>
9
<div id="not-the-app">
10
<!--Vue has no power here!-->
11
</div>
12
</body>
Нет монтажа на body
Вы будете извинены за то, что думаете, что body
тег будет лучшим местом для монтирования, поскольку есть много веских причин для того, чтобы захотеть контролировать body
классы, события тела и т. Д.
Проблема в том, что существуют плагины для браузера и сторонние скрипты, которые загрязняют body
их своими собственными классами, прослушивателями событий и даже произвольно добавляют свои дочерние узлы.
Это слишком страшно для Vue, так что body
тег не имеет границ. На самом деле, начиная с версии 2, если вы попытаетесь смонтировать там, вы получите это предупреждение:
Простой текст
xxxxxxxxxx
1
"Do not mount Vue to <html> or <body> - mount to normal elements instead."
Управление head
и body
теги
Итак, теперь, когда мы установили, что Vue должен монтироваться на своем собственном узле под body
, и он не может влиять на какую-либо часть DOM над этим узлом монтирования, как вы управляете body
или head
с помощью Vue?
Ответ: ты не можешь. Ну, не напрямую, по крайней мере. Все, что находится вне элемента mount, фактически невидимо для Vue.
Но в Vue есть нечто большее, чем рендеринг. Таким образом, даже несмотря на то, что элементы находятся вне его досягаемости, он все же может помочь вам в их достижении другими способами с помощью наблюдателей и хуков жизненного цикла.
Сценарий № 1: прослушивание ключевых событий
Допустим, вы создаете модальное окно с помощью Vue и хотите, чтобы пользователь мог закрыть окно с помощью клавиши escape .
Vue дает вам v-on
директиву для прослушивания событий, но если вы не сфокусированы на вводе формы, ключевые события отправляются из body
тега:
Поскольку body
Vue находится вне юрисдикции, вы не сможете заставить Vue прослушать это событие. Вам нужно будет настроить собственный приемник событий с помощью веб-API:
JavaScript
xxxxxxxxxx
1
var app = new Vue({
2
el: '#app',
3
data: {
4
modalOpen: false
5
}
6
});
7
document.addEventListener('keyup', function(evt) {
9
if (evt.keyCode === 27 && app.modalOpen) {
10
app.modalOpen = false;
11
}
12
});
Как Vue может помочь
Vue может помочь через хуки жизненного цикла . Во-первых, используйте созданный хук, чтобы добавить слушателя. Это гарантирует, что свойства данных, на которые вы ссылаетесь (то есть modalOpen
), наблюдаются при вызове обратного вызова.
Во-вторых, используйте уничтоженный хук, чтобы удалить слушателя, когда он больше не нужен, чтобы избежать утечек памяти.
JavaScript
xxxxxxxxxx
1
new Vue({
2
el: '#app',
3
data: {
4
modalOpen: false
5
},
6
methods: {
7
escapeKeyListener: function(evt) {
8
if (evt.keyCode === 27 && this.modalOpen) {
9
this.modalOpen = false;
10
}
11
}
12
},
13
created: function() {
14
document.addEventListener('keyup', this.escapeKeyListener);
15
},
16
destroyed: function() {
17
document.removeEventListener('keyup', this.escapeKeyListener);
18
},
19
});
Сценарий № 2: Управление body
классами
Когда пользователь открывает ваше модальное окно, вы хотите полностью отключить главное окно. Для этого вы можете сложить его за полупрозрачной панелью, чтобы на нее нельзя было нажать, и обрезать любое переполнение, чтобы его нельзя было прокрутить.
Чтобы предотвратить прокрутку, добавьте класс к телу (давайте назовем его modal-open
), который создает overflow: hidden
.
CSS
xxxxxxxxxx
1
body.modal-open {
2
overflow: hidden;
3
}
Очевидно, нам нужно динамически добавлять и удалять этот класс, так как мы все еще хотим разрешить прокрутку, когда модальное окно закрыто. Обычно мы используем v-bind:class
эту работу, но, опять же, вы не можете привязать body
атрибуты с помощью Vue, поэтому нам придется снова использовать Web API:
JavaScript
xxxxxxxxxx
1
// Modal opens
2
document.body.classList.add('modal-open');
3
// Modal closes
5
document.body.classList.remove('modal-closed');
Как Vue может помочь
Vue добавляет реактивные геттеры и сеттеры к каждому свойству данных, чтобы при изменении значения данных он знал об обновлении DOM. Vue позволяет вам написать собственную логику, которая подключается к реактивным изменениям данных через наблюдателей .
Vue будет выполнять любые обратные вызовы наблюдателя всякий раз, когда значение данных (в этом случае modalOpen
) изменяется. Мы будем использовать этот обратный вызов для обновления, чтобы добавить или удалить body
класс:
JavaScript
xxxxxxxxxx
1
var app = new Vue({
2
el: '#app',
3
data: {
4
modalOpen: false
5
},
6
watch: {
7
modalOpen: function(newVal) {
8
var className = 'modal-open';
9
if (newVal) {
10
document.body.classList.add(className);
11
} else {
12
document.body.classList.remove(className);
13
}
14
}
15
}
16
});