Начальный 8 мин чтения
Директивы Vue
Директивы — специальные атрибуты с префиксом v-, добавляющие реактивное поведение к DOM-элементам.
directivesv-ifv-forv-bindv-modelVue
Условный рендеринг
v-if / v-else-if / v-else
Полное добавление/удаление элемента из DOM:
<div v-if="user.role === 'admin'">Панель администратора</div>
<div v-else-if="user.role === 'moderator'">Панель модератора</div>
<div v-else>Обычный пользователь</div>
v-show
Скрытие через display: none — элемент остаётся в DOM:
<div v-show="isVisible">Контент</div>
Когда что использовать:
v-if— если условие меняется редко (избегает лишнего DOM)v-show— если условие меняется часто (избегает пересоздания)
v-if + <template>
<template v-if="isLoggedIn">
<header>...</header>
<main>...</main>
<!-- template не создаёт DOM-элемент -->
</template>
Рендеринг списков — v-for
<!-- Массив -->
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
<!-- Массив с индексом -->
<li v-for="(item, index) in items" :key="item.id">
{{ index + 1 }}. {{ item.name }}
</li>
<!-- Объект -->
<li v-for="(value, key, index) in user" :key="key">
{{ key }}: {{ value }}
</li>
<!-- Диапазон -->
<span v-for="n in 5" :key="n">{{ n }}</span>
<!-- 1 2 3 4 5 -->
Ключ :key
:key обязателен — помогает Vue эффективно обновлять список:
<!-- ❌ Плохо — нестабильный ключ -->
<li v-for="(item, i) in items" :key="i">
<!-- ✅ Хорошо — уникальный стабильный ID -->
<li v-for="item in items" :key="item.id">
Привязка атрибутов — v-bind
<img :src="imageUrl" :alt="imageAlt">
<a :href="link.url" :target="link.external ? '_blank' : undefined">
<!-- Объект атрибутов -->
<div v-bind="{ id: 'box', class: 'card', 'data-value': 42 }"></div>
<!-- Динамическое имя атрибута -->
<div :[dynamicAttr]="value"></div>
Привязка классов
<!-- Строка -->
<div :class="activeClass"></div>
<!-- Объект -->
<div :class="{ active: isActive, error: hasError }"></div>
<!-- Массив -->
<div :class="['base-class', isActive && 'active', errorClass]"></div>
<!-- Комбинированно -->
<div
class="static-class"
:class="{ active: isActive }"
></div>
Привязка стилей
<div :style="{ color: textColor, fontSize: `${size}px` }"></div>
<div :style="[baseStyles, overrideStyles]"></div>
Обработка событий — v-on
<!-- Полная запись -->
<button v-on:click="handleClick">Клик</button>
<!-- Сокращение -->
<button @click="handleClick">Клик</button>
<!-- Инлайн-обработчик -->
<button @click="count++">+</button>
<!-- С передачей события -->
<button @click="handleClick($event)">Клик</button>
<!-- Несколько событий -->
<input @focus="onFocus" @blur="onBlur">
Модификаторы событий
<!-- Предотвратить поведение по умолчанию -->
<form @submit.prevent="handleSubmit">
<!-- Остановить всплытие -->
<div @click.stop="handleClick">
<!-- Только один раз -->
<button @click.once="handleOnce">
<!-- Только на самом элементе, не на дочерних -->
<div @click.self="handleDivClick">
<!-- Клавиши -->
<input @keydown.enter="submit">
<input @keydown.esc="cancel">
<input @keydown.ctrl.enter="submitAndClose">
Двусторонняя привязка — v-model
<input v-model="text" placeholder="Введите текст">
<textarea v-model="message"></textarea>
<input type="checkbox" v-model="checked">
<input type="radio" v-model="picked" value="a">
<select v-model="selected">
<option value="a">A</option>
</select>
v-model — это сокращение для :value + @input:
<!-- Эквивалентно -->
<input :value="text" @input="text = $event.target.value">
Модификаторы v-model
<input v-model.trim="name"> <!-- Обрезать пробелы -->
<input v-model.number="age"> <!-- Преобразовать в число -->
<input v-model.lazy="email"> <!-- Обновлять при blur, не при каждом вводе -->
v-model в компонентах
<!-- Использование -->
<MyInput v-model="value" />
<!-- Эквивалентно -->
<MyInput :modelValue="value" @update:modelValue="value = $event" />
<!-- Компонент MyInput -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
v-once, v-memo, v-pre
<!-- Рендер один раз, игнорировать обновления -->
<span v-once>{{ staticText }}</span>
<!-- Обновлять только если зависимости изменились -->
<div v-memo="[item.id, item.name]">
<!-- Пропустит ре-рендер если id и name не изменились -->
</div>
<!-- Не обрабатывать как шаблон Vue -->
<pre v-pre>{{ это не будет вычислено }}</pre>