Синтаксис шаблонов
Vue использует синтаксис шаблонов, основанный на HTML. Он позволяет декларативно связывать отрисованный DOM с данными экземпляра компонента. Все шаблоны Vue являются синтаксически валидным HTML, который могут распарсить все HTML-парсеры и браузеры, соответствующих спецификации.
Под капотом Vue компилирует шаблоны в хорошо оптимизированный код JavaScript. В сочетании с системой реактивности Vue может определять минимальное число компонентов для перерисовки и при изменениях состояния приложения выполняет минимальное количество манипуляций с DOM.
Ну а если уже знакомы с концепцией виртуального DOM и предпочитаете использовать всю мощь JavaScript — вместо шаблонов можно писать render-функции напрямую, в том числе и с использованием JSX. Но следует учитывать, что они уже не будут обладать таким же уровнем оптимизации во время компиляции, как шаблоны.
Текстовые интерполяции
Наиболее простой способ связывания данных — текстовая интерполяция с использованием «Mustache»-синтаксиса из двойных фигурных скобок:
template
<span>Сообщение: {{ msg }}</span>
Такое выражение будет заменено значением свойства msg
соответствующего экземпляра компонента. Также оно будет обновляться при любом изменении значения свойства msg
.
Сырой HTML
Значение выражения в двойных фигурных скобках обрабатывается как обычный текст, а не как HTML. Для вывода в виде HTML необходимо использовать директиву v-html
:
template
<p>Двойные фигурные скобки: {{ rawHtml }}</p>
<p>Директива v-html: <span v-html="rawHtml"></span></p>
Двойные фигурные скобки: <span style="color: red">Красный текст.</span>
Директива v-html: Красный текст.
Здесь сталкиваемся с чем-то новым. Атрибут v-html
, который можно увидеть, называется директивой. Директивы имеют префикс v-
, чтобы обозначить, что это специальные атрибуты Vue, и как уже могли догадаться, они применяют особое реактивное поведение к отрисованному DOM. Тут, по сути, мы говорим «обновляй внутренний HTML этого элемента с помощью свойства rawHtml
текущего активного экземпляра.»
Содержимое тега span
будет заменено значением свойства rawHtml
, обработанного как обычный HTML — все привязки данных в нём будут проигнорированы. Запомните, что не получится скомпоновать итоговый шаблон из частей с помощью v-html
, так как движок шаблонов Vue не основан на строках. Вместо этого следует использовать компоненты, как фундаментальную единицу для сочетания и переиспользования элементов пользовательского интерфейса.
Предупреждение о безопасности
Динамическая отрисовка произвольного HTML-кода на сайте крайне опасна, так как может легко привести к XSS-уязвимостям. Используйте v-html
только в случаях доверенного содержимого и никогда не передавайте туда содержимое, которое может указывать пользователь.
Атрибуты
Синтаксис двойных фигурных скобок нельзя использовать внутри HTML-атрибутов. Вместо него следует использовать директиву v-bind
:
template
<div v-bind:id="dynamicId"></div>
Директива v-bind
сообщает Vue поддерживать атрибут id
элемента в синхронизации со свойством dynamicId
компонента. Если связанное значение будет null
или undefined
, то атрибут будет удален из отрисованного элемента.
Сокращённая запись
Поскольку v-bind
используется очень часто, у него есть специальный сокращённый синтаксис:
template
<div :id="dynamicId"></div>
Атрибуты именуемые с символа :
несколько отличаются от обычного HTML-кода, но в именах атрибутов допускается использование этого символа, а браузеры, поддерживающие Vue, могут их корректно обработать. Кроме того, в итоговой разметке их уже не будет. Сокращённый синтаксис полностью опционален, но вы, вероятно, оцените его по достоинству, когда узнаете больше о его использовании позже.
Далее в примерах в руководстве будет использоваться сокращённая запись, потому что она наиболее распространена у разработчиков Vue.
Одноименное сокращение
- Поддерживается только в версиях 3.4+
Если атрибут имеет то же имя, что и связываемое значение JavaScript, синтаксис можно еще больше сократить, опустив значение атрибута:
template
<!-- так же, как :id="id" -->
<div :id></div>
<!-- это также работает -->
<div v-bind:id></div>
Это похоже на синтаксис сокращения свойств при объявлении объектов в JavaScript. Обратите внимание, что эта функция доступна только во Vue 3.4 и выше.
Булевы атрибуты
Булевы атрибуты — атрибуты, которые указывают истинное/ложное значение своим присутствием в элементе. Например, disabled
— один из наиболее часто используемых булевых атрибутов.
В этом случае v-bind
будет работать немного иначе:
template
<button :disabled="isButtonDisabled">Кнопка</button>
Атрибут disabled
будет добавляться, когда значение isButtonDisabled
истинно. Он также будет добавляться, если значением будет пустая строка, для сохранения консистентности с <button disabled="">
. При использовании других ложных значений атрибут будет опущен.
Динамическая привязка нескольких атрибутов
Если есть объект JavaScript, представляющий несколько атрибутов, то он выглядит следующим образом:
js
const objectOfAttrs = {
id: 'container',
class: 'wrapper',
style: 'background-color:green'
}
Можно привязать их все к одному элементу, используя v-bind
без аргумента:
template
<div v-bind="objectOfAttrs"></div>
Использование JavaScript-выражений
До сих пор данные со свойствами в шаблонах связывались только по простым ключам. Но на самом деле Vue поддерживает всю мощь выражений JavaScript внутри привязки к данным:
template
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
Выражения будут выполняться как код JavaScript в области видимости текущего экземпляра компонента.
В шаблонах Vue выражения JavaScript можно использовать в следующих ситуациях:
- Внутри текстовых интерполяций (двойных фигурных скобок)
- В значении атрибутов директив Vue (специальные атрибуты, именуемые с
v-
)
Только выражения
Каждая привязка может содержать только одно выражение. Выражение — часть кода, которая может быть преобразована в значение. Это легко проверить, представив можно ли его использовать после return
.
Поэтому приведённый ниже код НЕ СРАБОТАЕТ:
template
<!-- НЕПРАВИЛЬНО -->
<!-- это определение переменной, а не выражение: -->
{{ var a = 1 }}
<!-- НЕПРАВИЛЬНО -->
<!-- операторы условий не будут работать, но можно -->
<!-- использовать условные операторы в тернарной форме: -->
{{ if (ok) { return message } }}
Вызов функций
Внутри привязки можно вызвать метод, объявленный в компоненте:
template
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
Совет
Функции, вызываемые в выражениях внутри привязки, будут вызываться каждый раз при обновлении компонента, поэтому НЕ ДОЛЖНЫ ИМЕТЬ НИКАКИХ ПОБОЧНЫХ ЭФФЕКТОВ, таких как изменение данных или запуск асинхронных операций.
Ограничения доступа к глобальным объектам
Выражения в шаблонах находятся в «песочнице» и имеют доступ только к ограниченному списку глобальных свойств, таких как Math
и Date
.
Глобальные свойства, которые явно не включены в список (например пользовательские свойства на window
) не будут доступны в шаблонных выражениях. Однако можно объявить дополнительные глобальные свойства для всех выражений Vue, добавив их с помощью app.config.globalProperties
.
Директивы
Директивы — специальные атрибуты с префиксом v-
. Vue предоставляет ряд встроенных директив, включая v-html
и v-bind
, которые уже встретили ранее.
В значении директивы ожидается одно выражение JavaScript (за исключением v-for
, v-on
и v-slot
, о которых поговорим далее). Задачей директивы является реактивное применение изменений к DOM, когда изменится значение выражения. Возьмём v-if
для примера:
template
<p v-if="seen">Сейчас меня видно</p>
Здесь директива v-if
удаляет или вставляет на страницу элемент <p>
на основании истинности выражения seen
.
Аргументы
Некоторые директивы могут принимать «аргумент», отделяемый двоеточием от названия директивы. Например, директиву v-bind
можно использовать для реактивного обновления атрибутов HTML:
template
<a v-bind:href="url"> ... </a>
<!-- сокращённая запись -->
<a :href="url"> ... </a>
В этом случае href
будет аргументом, указывающим директиве v-bind
связать атрибут href
элемента со значением выражения url
. В сокращённой записи всё, что находится перед аргументом (т.е., v-bind:
), сокращается до символа :
.
Другим примером может быть директива v-on
, которая отслеживает события DOM:
template
<a v-on:click="doSomething"> ... </a>
<!-- сокращённая запись -->
<a @click="doSomething"> ... </a>
В таком случае аргумент будет определять имя прослушиваемого события: click
. У директивы v-on
также есть сокращённая запись, с использованием символа @
. Подробнее об обработке событий поговорим далее.
Динамические аргументы
Можно использовать выражение JavaScript в аргументе директивы, для этого потребуется обернуть его в квадратные скобки:
template
<!--
Обратите внимание, есть ограничения для выражений аргументов, подробнее
об этом ниже, в разделах «Ограничения значений динамического аргумента»
и «Ограничения синтаксиса динамического выражения»
-->
<a v-bind:[attributeName]="url"> ... </a>
<!-- сокращённая запись -->
<a :[attributeName]="url"> ... </a>
Здесь attributeName
будет рассматриваться как выражение JavaScript, а его вычисленное значение использоваться в качестве финального значения для аргумента. Например, если в экземпляре компонента есть свойство данных attributeName
со значением "href"
, то это будет эквивалентно привязке v-bind:href
.
Аналогичным образом можно использовать динамические аргументы для созданий обработчика событий, в котором имя события будет определяться динамически:
template
<a v-on:[eventName]="doSomething"> ... </a>
<!-- сокращённая запись -->
<a @[eventName]="doSomething"> ... </a>
В этом примере, когда свойство в данных eventName
будет со значением "focus"
— итоговый обработчик v-on:[eventName]
будет эквивалентен v-on:focus
.
Ограничения значений динамического аргумента
Ожидается, что динамический аргумент после вычисления будет строкой, за исключением null
. Специальное значение null
можно использовать для явного удаления привязки. Использование любых других нестроковых значений будет выбрасывать предупреждения.
Ограничения синтаксиса динамического выражения
Для выражения динамического аргумента есть синтаксические ограничения, потому что некоторые символы, такие как пробелы и кавычки, не допускаются в именах атрибутов HTML. Например:
template
<!-- НЕПРАВИЛЬНО, это выбросит предупреждение компилятора. -->
<a :['foo' + bar]="value"> ... </a>
Для сложных динамических аргументов лучше выносить любые составные выражения в вычисляемые свойства, с которыми уже совсем скоро познакомимся.
При использовании шаблонов в DOM (шаблонов, написанных непосредственно в HTML-файле), также следует избегать прописных символов в именах ключей, потому что браузеры будут принудительно приводить имена атрибутов к нижнему регистру:
template
<a :[someAttr]="value"> ... </a>
В шаблонах DOM это преобразуется в нижний регистр :[someattr]
, поэтому если в компоненте не окажется свойства someattr
, то такой код НЕ СРАБОТАЕТ. На шаблоны внутри однофайловых компонентов это ограничение не распространяется.
Модификаторы
Модификаторы — специальные постфиксы, отделяемые точкой, которые обозначают, что директива должна быть привязана каким-то особенным образом. Например, модификатор .prevent
даёт указание директиве v-on
вызвать event.preventDefault()
при обработке произошедшего события:
template
<form @submit.prevent="onSubmit">...</form>
Другие примеры применения модификаторов увидим далее, когда будем изучать подробнее возможности v-on
и v-model
.
И, наконец, визуализация полного синтаксиса директивы: