Самый базовый способ вывести данные в шаблоне — двойные фигурные скобки **{{ }}**:
<template>
<p>{{ message }}</p>
<p>{{ count + 1 }}</p>
<p>{{ isOk ? 'Да' : 'Нет' }}</p>
<p>{{ text.toUpperCase() }}</p>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('Привет!')
const count = ref(5)
const isOk = ref(true)
const text = ref('hello')
</script>Внутри {{ }} можно писать любое JavaScript-**выражение** (но не инструкцию).
Для динамических атрибутов используется директива v-bind (сокращение — :):
<template>
<!-- Полная форма -->
<img v-bind:src="imageUrl" v-bind:alt="imageAlt">
<!-- Сокращённая форма (используется чаще) -->
<img :src="imageUrl" :alt="imageAlt">
<!-- Привязка класса -->
<div :class="{ active: isActive, error: hasError }">...</div>
<!-- Привязка стилей -->
<div :style="{ color: textColor, fontSize: size + 'px' }">...</div>
</template><template>
<div v-if="score >= 90">Отлично</div>
<div v-else-if="score >= 70">Хорошо</div>
<div v-else-if="score >= 50">Удовлетворительно</div>
<div v-else>Неудовлетворительно</div>
</template>**v-show** — альтернатива v-if. Элемент всегда рендерится, но скрывается через display: none:
<!-- v-if удаляет элемент из DOM -->
<div v-if="isVisible">Я либо есть, либо меня нет в DOM</div>
<!-- v-show скрывает через CSS, элемент остаётся в DOM -->
<div v-show="isVisible">Я всегда в DOM, просто скрыт</div>Используйте v-show если элемент часто переключается, v-if — если условие редко меняется.
<template>
<!-- Массив -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- Массив с индексом -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index + 1 }}. {{ item.name }}
</li>
</ul>
<!-- Объект -->
<ul>
<li v-for="(value, key) in userInfo" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
</template>Атрибут :key обязателен — Vue использует его для эффективного обновления списка.
v-model синхронизирует значение элемента формы с реактивной переменной:
<template>
<input v-model="username" placeholder="Введите имя">
<p>Имя: {{ username }}</p>
<input type="checkbox" v-model="isChecked"> Согласен
<p>Статус: {{ isChecked ? 'согласен' : 'не согласен' }}</p>
<select v-model="selectedCity">
<option value="moscow">Москва</option>
<option value="spb">Санкт-Петербург</option>
</select>
<p>Выбранный город: {{ selectedCity }}</p>
</template>
<script setup>
import { ref } from 'vue'
const username = ref('')
const isChecked = ref(false)
const selectedCity = ref('moscow')
</script>Директива v-on (сокращение — @) добавляет обработчики событий:
<template>
<button @click="handleClick">Нажми</button>
<button @click="count++">Инлайн</button>
<input @keyup.enter="submit">
<form @submit.prevent="handleSubmit">...</form>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function handleClick() {
console.log('Клик!')
}
function submit() {
console.log('Enter нажат')
}
function handleSubmit() {
console.log('Форма отправлена (без перезагрузки страницы)')
}
</script>Простой шаблонизатор — функция template(str, data) заменяет {{key}} на значения из объекта
// Vue шаблоны компилируются в render-функции,
// но идея замены плейсхолдеров та же.
// Реализуем простой шаблонизатор через регулярные выражения.
function template(str, data) {
return str.replace(/{{\s*(\w+)\s*}}/g, (match, key) => {
// match — всё совпадение: "{{ name }}"
// key — первая группа захвата: "name"
return key in data ? data[key] : match
})
}
// --- Примеры ---
const greeting = template('Привет, {{ name }}! Тебе {{ age }} лет.', {
name: 'Алексей',
age: 25
})
console.log(greeting)
// Привет, Алексей! Тебе 25 лет.
// Пробелы вокруг ключа не важны
const msg = template('{{city}} — красивый город', { city: 'Москва' })
console.log(msg)
// Москва — красивый город
// Неизвестный ключ остаётся как есть
const partial = template('{{ greeting }}, {{ unknown }}!', { greeting: 'Здравствуй' })
console.log(partial)
// Здравствуй, {{ unknown }}!
// Шаблон списка (более сложный случай)
function renderList(items, itemTemplate) {
return items.map(item => template(itemTemplate, item)).join('\n')
}
const users = [
{ name: 'Анна', role: 'admin' },
{ name: 'Борис', role: 'user' },
{ name: 'Вера', role: 'moderator' },
]
const list = renderList(users, '- {{ name }} ({{ role }})')
console.log('\nСписок пользователей:')
console.log(list)
// - Анна (admin)
// - Борис (user)
// - Вера (moderator)Самый базовый способ вывести данные в шаблоне — двойные фигурные скобки **{{ }}**:
<template>
<p>{{ message }}</p>
<p>{{ count + 1 }}</p>
<p>{{ isOk ? 'Да' : 'Нет' }}</p>
<p>{{ text.toUpperCase() }}</p>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('Привет!')
const count = ref(5)
const isOk = ref(true)
const text = ref('hello')
</script>Внутри {{ }} можно писать любое JavaScript-**выражение** (но не инструкцию).
Для динамических атрибутов используется директива v-bind (сокращение — :):
<template>
<!-- Полная форма -->
<img v-bind:src="imageUrl" v-bind:alt="imageAlt">
<!-- Сокращённая форма (используется чаще) -->
<img :src="imageUrl" :alt="imageAlt">
<!-- Привязка класса -->
<div :class="{ active: isActive, error: hasError }">...</div>
<!-- Привязка стилей -->
<div :style="{ color: textColor, fontSize: size + 'px' }">...</div>
</template><template>
<div v-if="score >= 90">Отлично</div>
<div v-else-if="score >= 70">Хорошо</div>
<div v-else-if="score >= 50">Удовлетворительно</div>
<div v-else>Неудовлетворительно</div>
</template>**v-show** — альтернатива v-if. Элемент всегда рендерится, но скрывается через display: none:
<!-- v-if удаляет элемент из DOM -->
<div v-if="isVisible">Я либо есть, либо меня нет в DOM</div>
<!-- v-show скрывает через CSS, элемент остаётся в DOM -->
<div v-show="isVisible">Я всегда в DOM, просто скрыт</div>Используйте v-show если элемент часто переключается, v-if — если условие редко меняется.
<template>
<!-- Массив -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- Массив с индексом -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index + 1 }}. {{ item.name }}
</li>
</ul>
<!-- Объект -->
<ul>
<li v-for="(value, key) in userInfo" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
</template>Атрибут :key обязателен — Vue использует его для эффективного обновления списка.
v-model синхронизирует значение элемента формы с реактивной переменной:
<template>
<input v-model="username" placeholder="Введите имя">
<p>Имя: {{ username }}</p>
<input type="checkbox" v-model="isChecked"> Согласен
<p>Статус: {{ isChecked ? 'согласен' : 'не согласен' }}</p>
<select v-model="selectedCity">
<option value="moscow">Москва</option>
<option value="spb">Санкт-Петербург</option>
</select>
<p>Выбранный город: {{ selectedCity }}</p>
</template>
<script setup>
import { ref } from 'vue'
const username = ref('')
const isChecked = ref(false)
const selectedCity = ref('moscow')
</script>Директива v-on (сокращение — @) добавляет обработчики событий:
<template>
<button @click="handleClick">Нажми</button>
<button @click="count++">Инлайн</button>
<input @keyup.enter="submit">
<form @submit.prevent="handleSubmit">...</form>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function handleClick() {
console.log('Клик!')
}
function submit() {
console.log('Enter нажат')
}
function handleSubmit() {
console.log('Форма отправлена (без перезагрузки страницы)')
}
</script>Простой шаблонизатор — функция template(str, data) заменяет {{key}} на значения из объекта
// Vue шаблоны компилируются в render-функции,
// но идея замены плейсхолдеров та же.
// Реализуем простой шаблонизатор через регулярные выражения.
function template(str, data) {
return str.replace(/{{\s*(\w+)\s*}}/g, (match, key) => {
// match — всё совпадение: "{{ name }}"
// key — первая группа захвата: "name"
return key in data ? data[key] : match
})
}
// --- Примеры ---
const greeting = template('Привет, {{ name }}! Тебе {{ age }} лет.', {
name: 'Алексей',
age: 25
})
console.log(greeting)
// Привет, Алексей! Тебе 25 лет.
// Пробелы вокруг ключа не важны
const msg = template('{{city}} — красивый город', { city: 'Москва' })
console.log(msg)
// Москва — красивый город
// Неизвестный ключ остаётся как есть
const partial = template('{{ greeting }}, {{ unknown }}!', { greeting: 'Здравствуй' })
console.log(partial)
// Здравствуй, {{ unknown }}!
// Шаблон списка (более сложный случай)
function renderList(items, itemTemplate) {
return items.map(item => template(itemTemplate, item)).join('\n')
}
const users = [
{ name: 'Анна', role: 'admin' },
{ name: 'Борис', role: 'user' },
{ name: 'Вера', role: 'moderator' },
]
const list = renderList(users, '- {{ name }} ({{ role }})')
console.log('\nСписок пользователей:')
console.log(list)
// - Анна (admin)
// - Борис (user)
// - Вера (moderator)Реализуй функцию `renderTemplate(template, data)`, которая принимает строку с плейсхолдерами вида {{name}} и объект данных, и возвращает строку с подставленными значениями. Если ключ отсутствует в data — подставь пустую строку. Пробелы внутри скобок должны игнорироваться ({{ name }} и {{name}} работают одинаково).
Используй str.replace(/{{\s*(\w+)\s*}}/g, (match, key) => {...}). Внутри колбэка верни data[key] !== undefined ? String(data[key]) : '' — это покроет случай когда ключ есть, но значение 0 или false.
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке