Шаблоны и интерполяция
Что такое шаблон
Шаблон Vue — обычный HTML + специальные директивы. Vue его компилирует в виртуальный DOM.
Интерполяция текста
Двойные фигурные скобки:
<template>
<h1>{{ title }}</h1>
<p>{{ message }}</p>
<span>{{ count + 1 }}</span>
<span>{{ isActive ? 'Активен' : 'Неактивен' }}</span>
</template>
Что можно:
- Переменные
- Выражения (без
if,for) - Тернарные операторы
- Вызовы методов
Нельзя:
- Многострочный код
- Операторы
if,for
Один раз — v-once
Если данные не меняются:
<h1 v-once>{{ title }}</h1>
Что даёт: Vue не будет следить за обновлением. Экономит ресурсы.
HTML из данных — v-html
Обычно {{ }} экранирует HTML. Если нужно вставить разметку:
<template>
<div v-html="htmlContent"></div>
</template>
<script setup>
import { ref } from 'vue';
const htmlContent = ref('<strong>Жирный</strong> текст');
</script>
⚠️ Опасно с пользовательскими данными — XSS-атаки. Используй только с доверенным контентом.
Привязка атрибутов — v-bind
Полная форма:
<img v-bind:src="imageUrl" v-bind:alt="imageAlt">
Краткая (:):
<img :src="imageUrl" :alt="imageAlt">
Динамические атрибуты:
<button :disabled="isLoading">Отправить</button>
<div :class="{ active: isActive, disabled: !isEnabled }"></div>
<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>
Привязка классов
Объектом:
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
Массивом:
<div :class="[baseClass, isActive ? 'active' : '', errorClass]"></div>
С обычным классом:
<div class="static" :class="{ active: isActive }"></div>
Привязка стилей
<div :style="{ color: 'red', fontSize: '16px' }"></div>
<div :style="styleObject"></div>
<div :style="[baseStyles, overrideStyles]"></div>
Привязка к свойствам
<input :value="message" :placeholder="placeholder">
<option :value="user.id">{{ user.name }}</option>
Булевы атрибуты
<button :disabled="isDisabled">OK</button>
<input :required="isRequired">
<input :checked="isChecked">
Если значение false — атрибут удаляется.
Несколько атрибутов через v-bind
Объектом:
<script setup>
import { ref } from 'vue';
const attrs = ref({
id: 'my-id',
class: 'my-class',
'data-value': 'test',
});
</script>
<template>
<div v-bind="attrs"></div>
</template>
Expression vs Statement
Expression — вычисляется в значение:
{{ count + 1 }}
{{ name.toUpperCase() }}
{{ items.length }}
Statement — выполняет действие:
<div @click="count++"></div>
<div @click="doSomething()"></div>
В {{ }} — только expression.
Полный пример
<template>
<div class="card" :class="{ featured: isFeatured }">
<h2>{{ title }}</h2>
<p v-if="description">{{ description }}</p>
<img :src="imageUrl" :alt="title">
<button :disabled="isLoading" @click="buy">
{{ isLoading ? 'Загрузка...' : 'Купить' }}
</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const title = ref('iPhone');
const description = ref('Новый iPhone 2026');
const imageUrl = ref('/iphone.jpg');
const isFeatured = ref(true);
const isLoading = ref(false);
function buy() {
isLoading.value = true;
setTimeout(() => isLoading.value = false, 1000);
}
</script>
<style scoped>
.card {
padding: 20px;
border: 1px solid #ddd;
}
.featured {
border-color: gold;
}
</style>
Итог
{{ }}— интерполяция текстаv-bind:attrили:attr— привязка атрибутов:class— объект/массив классов:style— объект/массив стилейv-html— HTML из данных (осторожно!)v-once— без обновления
Дальше — директивы v-if, v-for, v-bind.