Олег Марков
Использование шаблонов в Vue js для построения интерфейсов
Введение
Vue.js часто выбирают за то, что он позволяет быстро и удобно собирать сложные пользовательские интерфейсы. В основе философии Vue лежит идея гибких, декларативных шаблонов. Шаблоны здесь тесно связаны с реактивностью фреймворка и компонентным подходом. Вы оперируете знакомой разметкой и расширяете её динамическими возможностями с помощью специального синтаксиса. В этом материале я подробно расскажу, как устроены шаблоны во Vue, покажу их основные возможности и подскажу, как применять их на практике для строительства ваших интерфейсов.
Что такое шаблон во Vue.js
Шаблон во Vue — это кусок разметки (HTML), который описывает, как должен выглядеть компонент или часть интерфейса. Эти шаблоны расширены возможностями обработки данных: они поддерживают подстановку переменных, выражения, управляющие конструкции (например, условные блоки), события и многое другое.
Благодаря этому синтаксису вы управляете представлением данных декларативно, а Vue автоматически обновляет DOM, когда данные изменяются. В каждом компоненте Vue есть свой шаблон, и его структура определяет, как все отобразится на странице.
Основы работы с шаблонами
Основной синтаксис шаблонов
Шаблон обычно находится внутри блока <template>
. Пример самого простого компонента:
<template>
<div>
<h1>{{ title }}</h1> <!-- Интерполяция переменной -->
<p>Добро пожаловать!</p>
</div>
</template>
<script>
export default {
data() {
return {
title: 'Пример заголовка'
}
}
}
</script>
В этом примере мы используем двойные фигурные скобки {{ }}
для вывода значения переменной title
. Как только значение этой переменной меняется, Vue тут же обновляет отображение в браузере. Видите, насколько это просто?
Интерполяция данных
Вы можете подставлять любые данные из вашей модели прямо в шаблон:
<p>Сегодня: {{ new Date().toLocaleDateString() }}</p>
Также доступны все свойства и методы объекта компонента:
<span>Количество: {{ count }}</span>
Ограничения есть: внутри {{ }}
можно использовать только короткие однострочные выражения. Например, вот такой пример работать не будет:
{{ let a = 1; a + 2 }} <!-- Ошибка! Так нельзя -->
Динамические атрибуты с помощью v-bind
Если вам нужно сделать значение атрибута динамическим, используйте директиву v-bind
:
<img v-bind:src="imageUrl" alt="Фото"> <!-- Значение src — динамическое -->
Укороченная запись:
html
<img :src="imageUrl" alt="Фото">
Обработка событий с помощью v-on
Vue делает обработку событий очень простой. Пример с кнопкой:
<button v-on:click="increaseCounter">Увеличить</button>
<!-- или сокращенно -->
<button @click="increaseCounter">Увеличить</button>
Здесь при клике вызывается метод increaseCounter
, который вы определяете внутри компонента.
Управляющие конструкции: v-if, v-else, v-for
Условные конструкции
Иногда надо отобразить элемент только, если выполнено некоторое условие. Для этого есть директивы v-if
, v-else-if
, v-else
:
<p v-if="isLoggedIn">Приветствуем, пользователь!</p>
<p v-else>Пожалуйста, войдите в систему.</p>
Циклы
Если у вас есть массив, вы можете вывести его элементы с помощью v-for
:
<ul>
<li v-for="(item, idx) in items" :key="idx">{{ item.name }}</li>
</ul>
Vue требует атрибут :key
, чтобы оптимально отслеживать изменения.
Обработка пользовательского ввода: v-model
Давайте посмотрим, как двустороннее связывание данных решается с помощью v-model
:
<input v-model="username" placeholder="Введите имя">
<p>Вы ввели: {{ username }}</p>
Каждый раз, когда пользователь что-то вводит, переменная username
сразу же обновляется.
Работа с вложенными шаблонами и компонентами
Шаблоны для дочерних компонентов
Шаблоны можно вкладывать друг в друга через использование компонентов. Предположим, у вас есть компонент Button:
<!-- MyButton.vue -->
<template>
<button :class="type">{{ label }}</button>
</template>
<script>
export default {
props: ['label', 'type'],
}
</script>
Теперь вы используете этот компонент в шаблоне другого компонента:
<MyButton label="Сохранить" type="primary" />
Так вы легко структурируете проект из множества переиспользуемых компонентов, каждый со своим шаблоном.
Слоты: шаблоны с возможностью пользовательской вставки
Vue поддерживает расширенные шаблоны через слоты. Это вырезы внутри шаблона, которые заполняются содержимым вызывающего компонента. Например:
<!-- ParentComponent.vue -->
<template>
<ChildComponent>
<span>Переданный из родителя текст</span>
</ChildComponent>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<slot></slot> <!-- Здесь появится содержимое, переданное из parent -->
</div>
</template>
Также доступны именованные слоты и scoped slots. Они позволяют более гибко настраивать структуру вложенных компонентов.
Композиция шаблонов
Во Vue вы свободно комбинируете шаблоны из разных компонентов по своему усмотрению, создавая сложные интерфейсы из простых блоков.
Пример: представьте карточку товара с вложенной картинкой, кнопками и описанием — каждый блок можно сделать отдельным компонентом с собственным шаблоном.
Расширенные возможности шаблонов
Встраивание выражений и фильтров
В шаблонах часто применяется обработка данных на лету. Например:
<p>Цена: {{ price | currencyFilter }}</p>
Здесь фильтр currencyFilter
может быть написан вами и подключен глобально или локально к компоненту.
C версии Vue 3 фильтры убрали из ядра, рекомендуется использовать методы или вычисляемые свойства для преобразования данных:
<p>Цена: {{ formatCurrency(price) }}</p>
methods: {
formatCurrency(value) {
return value.toLocaleString() + ' ₽';
}
}
Динамические компоненты
С помощью директивы <component :is="componentName" />
можно рендерить разные компоненты по условию.
<component :is="currentComponent"></component>
data() {
return {
currentComponent: 'LoginForm'
}
}
Как только в currentComponent
окажется другое имя — например, 'RegisterForm'
, — Vue моментально поменяет видимый шаблон.
Фрагменты
Во Vue 3 появилась поддержка фрагментов — теперь шаблон может возвращать не единственный корневой элемент, а сразу несколько:
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>
Во Vue 2 требовался единственный корневой тег.
Условный рендеринг: v-show
v-if
удаляет или добавляет элемент в DOM полностью, а v-show
просто переключает CSS-свойство display
. Смотрите пример:
<p v-if="shouldShow">Этот элемент появится или исчезнет из DOM</p>
<p v-show="shouldShow">Этот элемент всегда в DOM, но скрыт через CSS</p>
Выбор между этими директивами зависит от того, насколько часто нужно переключать видимость и важна ли оптимизация производительности.
Ограничения и подводные камни шаблонов во Vue
Только выражения, не инструкции
Внутри двойных скобок нельзя использовать конструкции вроде if
, for
или объявлять новые переменные:
{{ let x = 10 }} <!-- Это не сработает -->
Работа с объектами и массивами
Vue не отслеживает добавление новых свойств у объектов или новые индексы у массивов так, чтобы они были реактивными (во Vue 2). Поэтому лучше заранее определять все необходимые свойства.
Безопасность: никакого HTML-инъектирования
По умолчанию, если вы передаёте строку в шаблон, она автоматически экранируется:
<p>{{ unsafeString }}</p>
Если хочется позволить рендерить HTML, используйте директиву v-html
, но будьте крайне осторожны:
<p v-html="rawHtml"></p>
Открывайте доступ только к доверенным данным, чтобы не допустить XSS-уязвимостей.
Одиночный корневой элемент (Vue 2)
До Vue 3 в шаблоне разрешался только один корневой тег:
<template>
<div>
<!-- Всё содержимое здесь -->
</div>
</template>
В Vue 3 это ограничение убрали.
Практические советы по использованию шаблонов
- Читайте официальную документацию по директивам: каждый год появляются новые возможности и синтаксические удобства.
- Разбивайте крупные шаблоны на небольшие компоненты: это улучшает читаемость, поддержку и переиспользуемость.
- Всегда задавайте атрибут
key
в циклахv-for
— это критически важно для производительности. - Для сложных условий используйте вычисляемые свойства вместо длинных выражений в шаблоне.
- Не забывайте про тестирование шаблонов: иногда из-за неправильной работы условий или типов может всё поломаться.
Заключение
Шаблоны во Vue.js — это мощный и удобный инструмент для построения динамичных, реактивных интерфейсов. Они предоставляют декларативный способ описания UI с помощью расширенного синтаксиса HTML, поддерживают динамические данные, условия, циклы, обработку событий и двустороннее связывание. Освоив шаблоны и их возможности, вы сможете строить надёжные и масштабируемые интерфейсы, легко разбивая их на отдельные компоненты и повторно используя код.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Как использовать условный класс для элемента в шаблоне Vue?
Вы можете использовать объект внутри директивы :class
:
<div :class="{ active: isActive, disabled: !isEnabled }">
Элемент с условиями по классам
</div>
active
будет добавлен, если переменнаяisActive
истинна.disabled
появляется, еслиisEnabled
ложно.
Как передать данные из родителя в дочерний компонент?
Используйте свойство props:
<!-- В родителе -->
<ChildComponent :title="parentTitle" />
<!-- В дочернем компоненте -->
props: ['title']
Как динамически изменить имя компонента в <component :is="...">
?
Создайте переменную в data, присваивайте ей строку — имя нужного компонента:
data() {
return {
current: 'FormA'
}
}
<component :is="current" />
Меняйте current
, чтобы подгружать другие компоненты.
Почему v-for требует атрибут key?
Без key
Vue не может надёжно отличать элементы списка при изменениях. Для правильной diff-логики и обновлений DOM всегда пишите уникальное :key
для каждого элемента списка:
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
Как сделать вложенные шаблоны более читаемыми?
Разбивайте сложные шаблоны на небольшие компоненты, используйте именованные и scoped слоты для гибкой передачи разметки. Всегда старайтесь держать шаблон одного компонента компактным — до 30-40 строк, если это возможно.