# Введение
Примечание
Уже изучили Vue 2 и хотите узнать, что нового во Vue 3? Посмотрите руководство по миграции!
# Что такое Vue.js?
Vue (произносится /vjuː/, примерно как view) — прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от фреймворков-монолитов, Vue создавался пригодным для постепенного внедрения. Его ядро в первую очередь решает задачи уровня представления (view), упрощая интеграцию с другими библиотеками и существующими проектами. С другой стороны, Vue полностью подходит и для разработки сложных одностраничных приложений (SPA, Single-Page Applications), если использовать его в комбинации с современными инструментами и дополнительными библиотеками (opens new window).
Если хотите узнать о Vue больше, прежде чем начать — посмотрите видео с рассказом об основных принципах работы на небольшом примере проекта.
# Начало работы
Совет
В руководстве предполагаются знания HTML, CSS и JavaScript на среднем уровне. Для новичков во фронтенд-разработке сразу начинать изучение с фреймворка может быть не лучшей идеей — возвращайтесь, разобравшись с основами! Наличие опыта работы с другими фреймворками может помочь, но не является обязательным.
Самый простой способ попробовать Vue.js — пример Hello World (opens new window). Открывайте его в соседней вкладке и практикуйтесь, изменяя по ходу изучения руководства.
На странице установки перечислено несколько вариантов как устанавливать Vue. Примечание: начинающим программистам не рекомендуем стартовать с vue-cli
, особенно если ещё не знакомы с инструментами сборки на основе Node.js.
# Декларативная отрисовка
В ядре Vue.js находится система, позволяющая декларативно отрисовывать данные в DOM с помощью простого синтаксиса шаблонов:
<div id="counter">
Счётчик: {{ counter }}
</div>
2
3
const Counter = {
data() {
return {
counter: 0
}
}
}
Vue.createApp(Counter).mount('#counter')
2
3
4
5
6
7
8
9
Вот и первое Vue-приложение! Хоть и выглядит как простая отрисовка строкового шаблона, но «под капотом» Vue выполнил немало работы. Данные и DOM теперь реактивно связаны. Как в этом убедиться? Посмотрите на пример ниже, где свойство counter
увеличивается каждую секунду и увидите, как изменяется DOM:
const Counter = {
data() {
return {
counter: 0
}
},
mounted() {
setInterval(() => {
this.counter++
}, 1000)
}
}
2
3
4
5
6
7
8
9
10
11
12
Counter: 0
Кроме интерполяции текста также можно связывать данные с атрибутами элементов:
<div id="bind-attribute">
<span v-bind:title="message">
Наведи на меня курсор на пару секунд, чтобы
увидеть динамически связанное значение title!
</span>
</div>
2
3
4
5
6
const AttributeBinding = {
data() {
return {
message: 'Страница загружена ' + new Date().toLocaleString()
}
}
}
Vue.createApp(AttributeBinding).mount('#bind-attribute')
2
3
4
5
6
7
8
9
See the Pen Attribute dynamic binding by Vue (@Vue) on CodePen.
Здесь повстречались с чем-то новым. Атрибут v-bind
называется директивой. Директивы именуются с префикса v-
, который обозначает, что это специальные атрибуты Vue, и, как уже можно догадаться, они добавляют особое реактивное поведение отрисованному DOM. В примере выше директива говорит «сохраняй значение title
этого элемента актуальным при изменении свойства message
в текущем активном экземпляре».
# Работа с пользовательским вводом
Чтобы позволить пользователям взаимодействовать с приложением, можно использовать директиву v-on
для обработчиков событий, которые будут вызывать методы экземпляра:
<div id="event-handling">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">Перевернуть сообщение</button>
</div>
2
3
4
const EventHandling = {
data() {
return {
message: 'Привет, Vue.js!'
}
},
methods: {
reverseMessage() {
this.message = this.message
.split('')
.reverse()
.join('')
}
}
}
Vue.createApp(EventHandling).mount('#event-handling')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
See the Pen Event handling by Vue (@Vue) on CodePen.
Обратите внимание, в методе не трогаем DOM и обновляем только состояние приложения — всеми манипуляциями с DOM занимается Vue, а в коде фокусируемся на логике работы.
Vue также предоставляет директиву v-model
, которая реализует двустороннюю привязку между элементом формы и состоянием приложения:
<div id="two-way-binding">
<p>{{ message }}</p>
<input v-model="message" />
</div>
2
3
4
const TwoWayBinding = {
data() {
return {
message: 'Привет, Vue!'
}
}
}
Vue.createApp(TwoWayBinding).mount('#two-way-binding')
2
3
4
5
6
7
8
9
See the Pen Two-way binding by Vue (@Vue) on CodePen.
# Условия и циклы
Управлять присутствием элемента в DOM тоже просто:
<div id="conditional-rendering">
<span v-if="seen">Сейчас меня видно</span>
</div>
2
3
const ConditionalRendering = {
data() {
return {
seen: true
}
}
}
Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
2
3
4
5
6
7
8
9
Пример выше демонстрирует возможность связывания данных не только с текстом и атрибутами, но и со структурой DOM. Кроме того, Vue имеет мощную систему анимаций, которая может автоматически применять эффекты переходов при добавлении, обновлении или удалении элементов.
В примере ниже можно изменять значение seen
с true
на false
чтобы увидеть эффект:
See the Pen Conditional rendering by Vue (@Vue) on CodePen.
Есть и некоторое количество других директив, каждая из которых обладает своей особой функциональностью. Например, директиву v-for
можно использовать для отображения списка элементов, используя данные из массива:
<div id="list-rendering">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
2
3
4
5
6
7
const ListRendering = {
data() {
return {
todos: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
]
}
}
}
Vue.createApp(ListRendering).mount('#list-rendering')
2
3
4
5
6
7
8
9
10
11
12
13
See the Pen List rendering by Vue (@Vue) on CodePen.
# Композиция приложения из компонентов
Компонентная система является ещё одной важной концепцией во Vue, потому что это абстракция, которая позволяет создавать большие приложения, состоящие из небольших, автономных и часто переиспользуемых компонентов. Если задуматься, то почти любой тип интерфейса приложения можно абстрактно представить в виде дерева компонентов:
Компонент во Vue — по сути экземпляр с предустановленными опциями. Его регистрация также проста: нужно создать объект компонента, как это уже делали с объектом app
, и указать его в родительской опции components
:
const TodoItem = {
template: `<li>Это одна из задач</li>`
}
// Создаём Vue-приложение
const app = Vue.createApp({
components: {
TodoItem // Регистрируем новый компонент
},
... // Остальные свойства для компонента
})
// Монтируем приложение Vue
app.mount(...)
2
3
4
5
6
7
8
9
10
11
12
13
14
После этого можно использовать его в шаблоне другого компонента:
<ol>
<!-- Создание экземпляра компонента todo-item -->
<todo-item></todo-item>
</ol>
2
3
4
Пока что во всех элементах списка будет один и тот же текст, что не очень-то интересно. Должна быть возможность передавать данные в дочерние компоненты из родительской области видимости. Доработаем компонент, чтобы он принимал входной параметр:
const TodoItem = {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
}
2
3
4
Теперь можно передавать свой текст для каждого из компонентов с помощью v-bind
:
<div id="todo-list-app">
<ol>
<!--
Теперь можно передавать каждому компоненту todo-item объект с информацией
о задаче, который может динамически изменяться. Также каждому компоненту
определяем "key", назначение которого разберём далее в руководстве.
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id"
></todo-item>
</ol>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
const TodoItem = {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
}
const TodoList = {
data() {
return {
groceryList: [
{ id: 0, text: 'Vegetables' },
{ id: 1, text: 'Cheese' },
{ id: 2, text: 'Whatever else humans are supposed to eat' }
]
}
},
components: {
TodoItem
}
}
const app = Vue.createApp(TodoList)
app.mount('#todo-list-app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
See the Pen Intro-Components-1 by Vue (@Vue) on CodePen.
Конечно, это несколько надуманный пример, но приложение удалось разделить на два блока поменьше. Дочерний компонент достаточно хорошо изолирован от родительского интерфейсом входных параметров. Теперь можно дорабатывать компонент <todo-item>
, изменяя его шаблон и логику и не затрагивать работу родительского приложения.
В больших приложениях разделение на компоненты становится жизненной необходимостью для сохранения управляемости разработки. Гораздо подробнее с компонентами продолжим разбираться далее в руководстве, но и сейчас можно взглянуть на (вымышленный) пример того, как может выглядеть шаблон приложения, использующего компоненты:
<div id="app">
<app-nav></app-nav>
<app-view>
<app-sidebar></app-sidebar>
<app-content></app-content>
</app-view>
</div>
2
3
4
5
6
7
# Отношение к пользовательским элементам
Можно заметить, что компоненты Vue похожи на пользовательские элементы, являющиеся частью спецификации веб-компонентов (opens new window). Некоторые элементы дизайна компонентов Vue (например, API слотов) действительно разрабатывались под влиянием этой спецификации ещё до того, как она была реализована в браузерах.
Но главное отличие в том, что компонентная модель Vue разработана как часть целостного фреймворка, предоставляющего множество дополнительных возможностей, необходимых при создании нетривиальных приложений, например, реактивный шаблонизатор и управление состоянием — оба этих аспекта не покрываются спецификацией.
Vue также предоставляет отличную поддержку как для использования, так и для создания пользовательских элементов. Более подробную информацию можно найти в разделе Vue и веб-компоненты.
# Готовы к большему?
В данный момент, мы пока что лишь вкратце затронули основные функции ядра Vue.js. В следующих разделах руководства мы будем разбирать более подробно эти, и другие интересные возможности. Поэтому, не забудьте прочитать его целиком!