Учебное пособие по Vue.js 3
Это структурированное учебное пособие по Vue.js 3 с фокусом на Composition API. Материал подойдёт как для начинающих, так и для тех, кто переходит с Options API.
Содержание
- Введение
- Установка и настройка проекта
- Основы: шаблоны, директивы, реактивность
- Computed properties и Watchers
- Жизненный цикл компонента
- Компоненты и передача данных (props / emits)
- Слоты (slots)
- Работа с формами (v-model)
- Маршрутизация – Vue Router 4
- Управление состоянием – Pinia
- Композиция и пользовательские хуки (composables)
- Что дальше?
1. Введение
Vue.js — прогрессивный JavaScript-фреймворк для создания пользовательских интерфейсов.
Vue 3 принёс:
- Composition API (лучшая организация кода в сложных компонентах)
- Улучшенную реактивность (Proxy)
- Более быструю производительность
- Поддержку TypeScript «из коробки»
2. Установка и настройка проекта
Рекомендуемый способ: Vite (быстрая сборка).
npm create vue@latest
При создании выберите нужные опции (TypeScript, Vue Router, Pinia, ESLint и др.).
После установки:
cd my-project npm install npm run dev
Для быстрого прототипа можно подключить Vue через CDN:
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
3. Основы: шаблоны, директивы, реактивность
3.1. Реактивные переменные
Composition API в компоненте:
<script setup>
import { ref } from 'vue'
const count = ref(0) // реактивная ссылка
function increment() {
count.value++ // .value – обязательно в JS
}
</script>
<template>
<button @click="increment">{{ count }}</button>
<!-- в шаблоне .value не нужен -->
</template>
ref() работает с любыми типами. Для объектов можно использовать reactive().
3.2. Основные директивы
- v-bind: или : – динамический атрибут
- v-on: или @ – обработчик события
- v-if / v-else-if / v-else – условный рендеринг
- v-for – списки
- v-model – двустороннее связывание (см. раздел 8)
Пример:
<template>
<div v-if="visible">Видимый блок</div>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</template>
4. Computed properties и Watchers
4.1. Computed (вычисляемые свойства)
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('Иван')
const lastName = ref('Петров')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
</script>
Computed автоматически пересчитывается при изменении зависимостей и кешируется.
4.2. Watchers (отслеживание изменений)
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`Было ${oldVal}, стало ${newVal}`)
})
</script>
5. Жизненный цикл компонента
В Composition API хуки вызываются внутри setup (или <script setup>):
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue'
onMounted(() => {
console.log('Компонент смонтирован')
})
onUnmounted(() => {
console.log('Компонент уничтожен')
})
</script>
Основные хуки: onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted.
6. Компоненты и передача данных (props / emits)
6.1. Передача данных от родителя к ребёнку (props)
Ребёнок (Child.vue):
<script setup>
const props = defineProps(['title', 'count'])
// или с валидацией:
// defineProps({
// title: String,
// count: { type: Number, required: true }
// })
</script>
<template>
<h2>{{ title }}</h2>
<p>Счётчик: {{ count }}</p>
</template>
Родитель:
<Child title="Заголовок" :count="42" />
6.2. Отправка событий наверх (emits)
Ребёнок:
<script setup>
const emit = defineEmits(['update'])
function handleClick() {
emit('update', 'новое значение')
}
</script>
Родитель:
<Child @update="handleUpdate" />
7. Слоты (slots)
Позволяют передавать разметку в компонент.
Компонент Card.vue:
<template>
<div class="card">
<header><slot name="header">По умолчанию</slot></header>
<main><slot /></main>
<footer><slot name="footer" /></footer>
</div>
</template>
Использование:
<Card> <template #header>Мой заголовок</template> <p>Основной контент</p> <template #footer>Подвал</template> </Card>
8. Работа с формами (v-model)
Двустороннее связывание с ref:
<script setup>
import { ref } from 'vue'
const name = ref('')
const isActive = ref(false)
const selectedOption = ref('')
</script>
<template>
<input v-model="name" placeholder="Введите имя" />
<input type="checkbox" v-model="isActive" />
<select v-model="selectedOption">
<option value="1">Опция 1</option>
<option value="2">Опция 2</option>
</select>
</template>
Кастомный v-model на компоненте можно реализовать через modelValue prop и update:modelValue событие.
9. Маршрутизация – Vue Router 4
Установка: npm install vue-router@4
Файл router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomePage from '../views/HomePage.vue'
import AboutPage from '../views/AboutPage.vue'
const routes = [
{ path: '/', component: HomePage },
{ path: '/about', component: AboutPage }
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
В App.vue:
<template>
<nav>
<router-link to="/">Главная</router-link>
<router-link to="/about">О нас</router-link>
</nav>
<router-view /> <!-- место рендера текущего компонента -->
</template>
10. Управление состоянием – Pinia
Pinia – официальный стейт-менеджер для Vue 3.
Установка: npm install pinia
Создание store (stores/counter.js):
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
Использование в компоненте:
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<p>{{ counter.count }}</p>
<button @click="counter.increment">+1</button>
</template>
11. Композиция и пользовательские хуки (composables)
Composable – функция, которая использует реактивные API Vue и переиспользует логику.
Пример composable useMouse.js:
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.clientX
y.value = event.clientY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
Использование в компоненте:
<script setup>
import { useMouse } from './useMouse'
const { x, y } = useMouse()
</script>
<template>Координаты мыши: {{ x }}, {{ y }}</template>
12. Что дальше?
- Официальная документация: vuejs.org
- Инструменты: Vue Devtools, Volar (VS Code плагин)
- TypeScript + Vue – добавит строгую типизацию
- Тестирование: Vitest (unit), Cypress (e2e)
- Серверный рендеринг: Nuxt 3 (фреймворк на основе Vue)
Примечание: Весь код в пособии использует Composition API с <script setup> – это современный стандарт. Все примеры самодостаточны и могут быть скопированы в проект для проверки.