1. Что такое Vue 3
Что такое Vue 3? 🌱
Заголовок раздела «Что такое Vue 3? 🌱»Представь, что ты хочешь сделать страницу интерактивной. Без фреймворка — это DOM-манипуляции, querySelector, addEventListener, ручное обновление HTML. Скучно и многословно. Vue говорит: «Опиши, как должен выглядеть интерфейс при каждом состоянии данных — я сам разберусь с обновлением DOM». Вот и вся магия! ✨
Vue — прогрессивный фреймворк 📈
Заголовок раздела «Vue — прогрессивный фреймворк 📈»«Прогрессивный» означает — используй столько, сколько нужно:
<!-- Уровень 1: просто скрипт в HTML — без сборщика! --><div id="app"> <h1>{{ title }}</h1> <button @click="count++">Кликов: {{ count }}</button></div><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><script> Vue.createApp({ data() { return { title: 'Мой счётчик', count: 0 } } }).mount('#app')</script>npm create vue@latest my-spa# Уровень 3: Full-stack SSR с Nuxt 3npx nuxi init my-nuxt-appОдин фреймворк — три уровня применения. Растёшь вместе с проектом!
Архитектура Vue 3 — под капотом 🔧
Заголовок раздела «Архитектура Vue 3 — под капотом 🔧»Монорепо и пакеты
Заголовок раздела «Монорепо и пакеты»Vue 3 написан как монорепо из отдельных пакетов:
@vue/reactivity — система реактивности (ref, reactive, computed, watch)@vue/runtime-core — ядро рантайма (Virtual DOM, компоненты, lifecycle)@vue/runtime-dom — DOM-специфичный рантайм (директивы, события DOM)@vue/compiler-core — парсер и компилятор шаблонов@vue/compiler-dom — компилятор для DOM@vue/compiler-sfc — компилятор SFC (.vue файлов)@vue/server-renderer — SSR рендерингВся реактивность — отдельный пакет! Можно использовать @vue/reactivity в Node.js без DOM.
Система реактивности на Proxy 🪞
Заголовок раздела «Система реактивности на Proxy 🪞»Vue 3 использует JavaScript Proxy — это принципиально отличает его от Vue 2 с Object.defineProperty:
// Под капотом Vue 3 — упрощённоfunction reactive(obj: object) { return new Proxy(obj, { get(target, key) { // 📌 Регистрируем зависимость (track) track(target, key) return Reflect.get(target, key) }, set(target, key, value) { const result = Reflect.set(target, key, value) // 🔔 Уведомляем подписчиков (trigger) trigger(target, key) return result } })}Преимущества перед Vue 2 / Object.defineProperty:
- ✅ Перехватывает добавление новых свойств (Vue 2 не умел!)
- ✅ Перехватывает удаление свойств
- ✅ Работает с массивами без патчинга (
push,splice) - ✅ Работает с
Map,Set,WeakMap
Паттерн MVVM в Vue 🏛️
Заголовок раздела «Паттерн MVVM в Vue 🏛️»Vue реализует паттерн MVVM (Model-View-ViewModel):
┌─────────────────────────────────────────────┐│ Vue компонент ││ ││ ┌─────────┐ Data Binding ┌──────────┐ ││ │ View │ ◄──────────────► │ViewModel │ ││ │ (шаблон)│ │ (script)│ ││ └─────────┘ └──────────┘ ││ ▲ │ ││ │ Observer ▼ ││ └──────────────────── ┌──────────┐ ││ │ Model │ ││ │ (data) │ ││ └──────────┘ │└─────────────────────────────────────────────┘// ViewModel — скрипт компонентаconst count = ref(0) // ◄── Model (данные)const doubled = computed(() => count.value * 2) // ◄── ViewModel (логика)<!-- View — шаблон --><template> <button @click="count++">{{ count }}</button> <!-- двусторонняя связь --> <p>Удвоенное: {{ doubled }}</p></template>Virtual DOM — зачем он нужен? 🌳
Заголовок раздела «Virtual DOM — зачем он нужен? 🌳»Прямые манипуляции с DOM — медленные. DOM браузера — это сложный C++ объект. Каждое обращение к нему дорого стоит.
Virtual DOM — это лёгкое JS-представление DOM-дерева:
// Реальный DOM — тяжёлый C++ объектdocument.createElement('div') // ≈ 500+ свойств!
// Virtual DOM в Vue 3 — просто объектconst vnode = { type: 'div', props: { class: 'card', onClick: handler }, children: [ { type: 'h2', props: null, children: 'Заголовок' }, { type: 'p', props: null, children: 'Текст' } ]}Алгоритм обновления (Diffing):
Старый VDOM Новый VDOM <div> <div> ├─ <h2>A</h2> ├─ <h2>A</h2> ← не изменился, пропускаем ├─ <p>Hello</p> ├─ <p>World</p> ← изменился! обновляем только текст └─ <span>1</span> └─ <span>2</span> ← изменился! обновляем только текстVue 3 ещё умнее — компилятор анализирует шаблон и помечает статические части, которые никогда не изменятся:
<template> <div> <h1>Статичный заголовок</h1> <!-- ← Vue 3 помечает как статику, пропускает при обновлении --> <p>{{ dynamicText }}</p> <!-- ← только это обновляется --> </div></template>Vue 3 vs Vue 2 — главные отличия 🔄
Заголовок раздела «Vue 3 vs Vue 2 — главные отличия 🔄»1. Composition API (новое в Vue 3)
Заголовок раздела «1. Composition API (новое в Vue 3)»// Vue 2 — Options APIexport default { data() { return { count: 0, user: null } }, computed: { doubled() { return this.count * 2 } }, methods: { increment() { this.count++ }, async fetchUser() { this.user = await api.getUser() } }, mounted() { this.fetchUser() }}
// Vue 3 — Composition API (гораздо гибче!)import { ref, computed, onMounted } from 'vue'
const count = ref(0)const doubled = computed(() => count.value * 2)const increment = () => count.value++
const user = ref(null)const fetchUser = async () => { user.value = await api.getUser()}onMounted(fetchUser)2. Fragments — несколько корневых элементов
Заголовок раздела «2. Fragments — несколько корневых элементов»<!-- Vue 2 — ОШИБКА! нужен один корень --><template> <h1>Заголовок</h1> <p>Параграф</p></template>
<!-- Vue 3 — OK! Fragments! 🎉 --><template> <h1>Заголовок</h1> <p>Параграф</p></template>3. Teleport — рендеринг вне дерева
Заголовок раздела «3. Teleport — рендеринг вне дерева»<!-- Vue 3 — рендерим модальное окно в body, не в компоненте --><template> <button @click="showModal = true">Открыть</button>
<Teleport to="body"> <div v-if="showModal" class="modal"> <p>Я рендерюсь прямо в body! 🎯</p> </div> </Teleport></template>4. Suspense — async компоненты с fallback
Заголовок раздела «4. Suspense — async компоненты с fallback»<!-- Vue 3 --><template> <Suspense> <template #default> <AsyncUserProfile /> <!-- загружается асинхронно --> </template> <template #fallback> <LoadingSpinner /> <!-- показывается пока грузится --> </template> </Suspense></template>5. TypeScript — из коробки
Заголовок раздела «5. TypeScript — из коробки»// Vue 3 написан на TypeScript, поэтому типы идеальныimport { ref, Ref } from 'vue'
interface User { id: number name: string email: string}
const user: Ref<User | null> = ref(null)// TypeScript знает всё о user.value!6. Производительность
Заголовок раздела «6. Производительность»| Метрика | Vue 2 | Vue 3 | Улучшение |
|---|---|---|---|
| Размер бандла | 22.9KB | 13.5KB (с tree-shaking) | −41% |
| Скорость рендера | базовая | +55% быстрее | |
| Использование памяти | базовое | −54% меньше | |
| Скорость обновления | базовая | +133% быстрее |
createApp — точка входа в Vue 3 🚪
Заголовок раздела «createApp — точка входа в Vue 3 🚪»// main.ts — входной файл приложенияimport { createApp } from 'vue'import App from './App.vue'import router from './router'import { createPinia } from 'pinia'
// Создаём приложениеconst app = createApp(App)
// Подключаем плагиныapp.use(router)app.use(createPinia())
// Регистрируем глобальные компонентыapp.component('BaseButton', BaseButton)
// Регистрируем глобальные директивыapp.directive('focus', { mounted: el => el.focus() })
// Глобальные свойства (аналог Vue.prototype в Vue 2)app.config.globalProperties.$http = axios
// Монтируем в DOMapp.mount('#app')Важно: в Vue 3 нет глобального Vue объекта — только инстансы приложения. Можно создать несколько независимых приложений на одной странице!
Экосистема и инструменты 🛠️
Заголовок раздела «Экосистема и инструменты 🛠️»Volar (VS Code)
Заголовок раздела «Volar (VS Code)»Замени Vetur на Volar — официальный Language Server для Vue 3:
{ "recommendations": [ "Vue.volar", // подсветка, автодополнение, типы "Vue.vscode-typescript-vue-plugin" // TypeScript поддержка ]}Vue DevTools
Заголовок раздела «Vue DevTools»Расширение для Chrome/Firefox — просматривай дерево компонентов, состояние, события:
🛠️ Vue DevTools показывает:├── 🧩 Components — дерево компонентов и их props/data├── 🍍 Pinia — состояние всех сторов├── 🗺️ Router — текущий маршрут, история├── ⏱️ Timeline — события в хронологии└── ⚡ Performance — скорость рендера компонентовПервый настоящий компонент ✍️
Заголовок раздела «Первый настоящий компонент ✍️»<!-- HelloVue.vue — Single File Component --><template> <div class="hello"> <h1>{{ greeting }}, {{ name }}! 👋</h1> <p>Ты нажал кнопку {{ count }} раз(а)</p> <button @click="increment">Нажми меня!</button> <input v-model="name" placeholder="Введи имя..." /> </div></template>
<script setup lang="ts">import { ref, computed } from 'vue'
// Реактивные данныеconst name = ref('Яша')const count = ref(0)
// Вычисляемое свойствоconst greeting = computed(() => { return count.value > 5 ? 'Привет-привет' : 'Привет'})
// Функцияconst increment = () => { count.value++}</script>
<style scoped>.hello { padding: 20px; text-align: center;}
button { background: #42b883; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;}</style>Три секции Single File Component:
<template>— HTML с Vue-директивами<script setup>— логика на TypeScript<style scoped>— CSS изолированный в компоненте
Когда Vue 3 — правильный выбор? 🎯
Заголовок раздела «Когда Vue 3 — правильный выбор? 🎯»✅ ВЫБИРАЙ Vue 3 если: ├── Команда знает HTML/CSS/JS — Vue очень интуитивен ├── Нужен быстрый старт — документация лучшая в классе ├── SPA, дашборды, интерактивные сайты ├── Хочешь гибкость: CDN → Vite → Nuxt └── Важна читаемость шаблонов
❌ РАССМОТРИ АЛЬТЕРНАТИВЫ если: ├── Огромная enterprise команда → Angular ├── Нужен максимальный найм → React ├── Нативное мобильное приложение → React Native / Flutter └── Статичный сайт без интерактивности → HTML/CSSРезюме 📝
Заголовок раздела «Резюме 📝»Vue 3 — это:
- Прогрессивный фреймворк: от CDN-скрипта до full-stack SSR
- Реактивность через Proxy: умнее и быстрее Vue 2
- Composition API: код по фичам, не по типам опций
- Отличный TypeScript: написан на TS, типы из коробки
- Маленький бандл: tree-shaking, только то что используешь
- Огромная экосистема: Vite, Pinia, Vue Router, VueUse, Nuxt 3
Следующий шаг — установка и создание первого проекта с Vite! ⚡