Для приложения Vue обычной практикой является использование DOM в качестве шаблона, поскольку это самая быстрая и простая в настройке архитектура.
Однако эта практика имеет несколько уловов, которые делают ее нежелательным выбором для любого серьезного проекта. Например, разметка, которую вы пишете для шаблона DOM, не всегда совпадает с тем, что вы получаете при запуске приложения.
В этой статье я объясню проблемы с использованием DOM в качестве шаблона и предложу несколько альтернатив.
DOM как шаблон
Эта el
опция используется для монтирования экземпляра Vue к элементу в DOM. Если нет template
или render
опция присутствует, Vue будет использовать любой существующий контент в монтажном элементе в качестве шаблона.
JavaScript
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset="UTF-8">
5
<title>title</title>
6
</head>
7
<body>
8
<div id="app">
9
<!--This markup will be the template of the root instance-->
10
<h1>My Vue.js App</h1>
11
<p>{{ message }}</p>
12
</div>
13
</body>
14
</html>
15
new Vue({
17
el: '#app',
18
data: {
19
message: 'Hello world'
20
}
21
});
Этот подход позволяет быстро приступить к работе, но вам следует отказаться от него, потому что:
- Разметка, которую вы пишете не всегда, что вы получаете.
- Синтаксические конфликты с шаблонизаторами.
- Несовместимость с рендерингом на стороне сервера.
- Требуется компиляция шаблона во время выполнения.
Вам также может понравиться:
Как и почему мы переехали на Vue.js
Разметка! = ДОМ
Давайте сделаем различие между разметкой и DOM . Разметка - это HTML, который вы пишете. Затем браузер проанализирует это и превратит в DOM.
Vue использует DOM в качестве шаблона, а не разметку, которую вы пишете. Почему это проблема? Парсер DOM и Vue не всегда согласны с тем, что является приемлемой разметкой. Нестандартная разметка может быть изменена или удалена со страницы, что может привести к непредсказуемым результатам.
Например, у вас может быть пользовательский компонент, my-row
который отображается как tr
и будет логически использоваться следующим образом:
HTML
xxxxxxxxxx
1
<table>
2
<my-row></my-row>
3
</table>
Поскольку tr
в a разрешено только внутри table
, браузер будет поднимать my-row
элемент над таблицей во время анализа документа. К тому времени, когда Vue запустится, у вас будет это:
HTML
xxxxxxxxxx
1
<my-row></my-row>
2
<table></table>
Есть также классные нестандартные функции для шаблонов Vue, которые DOM-парсер удалит:
Самозакрывающиеся теги: если вашему компоненту не требуется слот, Vue позволяет сделать его самозакрывающимся элементом.
HTML
xxxxxxxxxx
1
<!--Will be discarded by the DOM parser-->
2
<my-component/>
Компоненты без кебаба: HTML не учитывает регистр, что означает, что вы ограничены компонентами кебаба в шаблоне. Впрочем, Vue с удовольствием примет camelCase или PascalCase. То же самое с реквизитом.
HTML
xxxxxxxxxx
1
<!--Will be discarded by the DOM parser-->
2
<PascalCaseComponent camelCaseProp="test"></PascalCaseComponent>
Ни одна из этих проблем не возникает, если вы используете строковые шаблоны (или функции рендеринга), поскольку анализатор DOM здесь не является фактором.
Столкновение с шаблонизаторами
Если вы используете Vue.js в сочетании с движком шаблонов, любой общий синтаксис может быть проблематичным.
Например, Handlebars и Laravel Blade используют {{ }}
синтаксис двойных фигурных скобок, который использует Vue. Когда ваш шаблон обработан, шаблонизатор не сможет различить синтаксис Vue, что вызовет проблему.
Обычно это легко обойти, избегая синтаксиса Vue (например, в Blade вы можете поставить @
перед скобками, и Blade будет знать, что их игнорировать, например ). Но все же, это еще одна вещь, чтобы раздражать вас.@{{ forVue }}
Рендеринг на стороне сервера
Вы просто не можете использовать шаблон DOM, если хотите рендерить свое приложение Vue на стороне сервера, поскольку HTML-документ не является вводом процесса SSR.
Избегание шаблонов DOM
Как вы можете создать приложение Vue.js без шаблона DOM или хотя бы небольшого?
1. Абстрактная разметка для компонентов
Ваш корневой экземпляр может содержать некоторое состояние, но, как правило, вы хотите, чтобы любая логика и разметка представления были абстрагированы от компонентов, так что это выходит за рамки вашего DOM-шаблона.
Однофайловые компоненты - лучший выбор. Если вы не можете включить шаг сборки в свой проект и не любите писать свои шаблоны в виде строк JavaScript (кто это делает), вы можете попробовать x-templates .
Рентгеновские шаблоны
С помощью x-templates ваш шаблон по-прежнему определяется на странице, но в теге script, и поэтому будет избегать обработки анализатором DOM. Тег сценария отмечен значком text/x-template
и указан id
в определении вашего компонента.
HTML
xxxxxxxxxx
1
Vue.component('my-component', {
2
template: '#my-component'
3
}
4
5
<script type="text/x-template" id="my-component">
6
<div>My component template</div>
7
<NonStandardMarkupIsFineHere/>
8
</script>
2. Крепление к пустому узлу с функцией рендеринга
Абстрагирование разметки на компоненты наталкивается на стену, когда вы понимаете, что вам все еще нужно объявить свой корневой компонент в шаблоне DOM.
HTML
xxxxxxxxxx
1
<div id="app">
2
<!-- We still have a DOM template 🙁 -->
3
<app></app>
4
</div>
Если вы хотите полностью исключить шаблон DOM, вы можете смонтировать компоненты корневого уровня с помощью функции рендеринга.
Допустим, у вас есть один всеобъемлющий компонент, который объявляет другие компоненты вызываемыми App
. App
может быть объявлено с помощью render
функции и смонтировано на пустом узле, поскольку функции рендеринга заменят свой элемент монтирования.
JavaScript
xxxxxxxxxx
1
<div id="app"></div>
2
new Vue({
5
el: '#app',
6
components: {
7
App
8
},
9
render: function(createElement) {
10
return createElement(App);
11
}
12
})
И с этим ваше приложение свободно от любого шаблона DOM!
Если вы можете удалить все строковые и DOM-шаблоны из своего приложения, вы можете использовать меньшую сборку Vue только для времени выполнения. Это идеальная архитектура проекта, которую вы увидите в шаблонах vue-cli.
Резюме
- Шаблоны DOM проблематичны, так как анализатор DOM может испортить вашу разметку. Также существует вероятность столкновения с движками шаблонов и несовместимости с рендерингом на стороне сервера.
- Чтобы свести к минимуму ваш шаблон DOM, абстрагируйте вашу разметку в компоненты.
- Чтобы полностью исключить шаблон DOM, вам необходимо смонтировать компонент корневого уровня с помощью функции рендеринга.