# Введение

Примечание

Уже изучили Vue 2 и хотите узнать что нового во Vue 3? Посмотрите руководство по миграции!

# Что такое Vue.js?

Vue (произносится /vjuː/, примерно как view) — прогрессивный фреймворк для создания пользовательских интерфейсов. В отличие от фреймворков-монолитов, Vue создавался пригодным для постепенного внедрения. Его ядро в первую очередь решает задачи уровня представления (view), упрощая интеграцию с другими библиотеками и существующими проектами. С другой стороны, Vue полностью подходит и для разработки сложных одностраничных приложений (SPA, Single-Page Applications), если использовать его в комбинации с современными инструментами и дополнительными библиотеками (opens new window).

Если хотите узнать о Vue больше, прежде чем начать — посмотрите видео с рассказом об основных принципах работы на небольшом примере проекта.

Посмотрите бесплатный видео-курс на Vue Mastery

# Начало работы

Установка

Совет

В руководстве предполагаются знания HTML, CSS и JavaScript на среднем уровне. Для новичков во фронтенд-разработке сразу начинать изучение с фреймворка может быть не лучшей идеей — возвращайтесь, разобравшись с основами! Наличие опыта работы с другими фреймворками может помочь, но не является обязательным.

Самый простой способ попробовать Vue.js — пример Hello World (opens new window). Открывайте его в соседней вкладке и практикуйтесь, изменяя по ходу изучения руководства.

На странице установки перечислены несколько вариантов как устанавливать Vue. Примечание: начинающим программистам не рекомендуем стартовать с vue-cli, особенно если ещё не знакомы с инструментами сборки на основе Node.js.

# Декларативная отрисовка

В ядре Vue.js находится система, позволяющая декларативно отрисовывать данные в DOM с помощью простого синтаксиса шаблонов:

<div id="counter">
  Счётчик: {{ counter }}
</div>
1
2
3
const Counter = {
  data() {
    return {
      counter: 0
    }
  }
}

Vue.createApp(Counter).mount('#counter')
1
2
3
4
5
6
7
8
9

Вот и первое Vue-приложение! Хоть и выглядит как простая отрисовка строкового шаблона, но «под капотом» Vue выполнил немало работы. Данные и DOM теперь реактивно связаны. Как в этом убедиться? Посмотрите на пример ниже, где свойство counter увеличивается каждую секунду и увидите, как изменяется DOM:








 
 
 



const Counter = {
  data() {
    return {
      counter: 0
    }
  },
  mounted() {
    setInterval(() => {
      this.counter++
    }, 1000)
  }
}
1
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>
1
2
3
4
5
6
const AttributeBinding = {
  data() {
    return {
      message: 'Страница загружена ' + new Date().toLocaleString()
    }
  }
}

Vue.createApp(AttributeBinding).mount('#bind-attribute')
1
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>
1
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')
1
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>
1
2
3
4
const TwoWayBinding = {
  data() {
    return {
      message: 'Привет, Vue!'
    }
  }
}

Vue.createApp(TwoWayBinding).mount('#two-way-binding')
1
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>
1
2
3
const ConditionalRendering = {
  data() {
    return {
      seen: true
    }
  }
}

Vue.createApp(ConditionalRendering).mount('#conditional-rendering')
1
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>
1
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')
1
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:

// Создаём приложение Vue
const app = Vue.createApp(...)

// Определяем новый компонент с именем todo-item
app.component('todo-item', {
  template: `<li>Это одна из задач</li>`
})

// Монтируем приложение Vue
app.mount(...)
1
2
3
4
5
6
7
8
9
10

После этого можно использовать его в шаблоне другого компонента:

<ol>
  <!-- Создание экземпляра компонента todo-item -->
  <todo-item></todo-item>
</ol>
1
2
3
4

Пока что во всех элементах списка будет один и тот же текст, что не очень-то интересно. Должна быть возможность передавать данные в дочерние компоненты из родительской области видимости. Доработаем компонент, чтобы он принимал входной параметр:

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})
1
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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const TodoList = {
  data() {
    return {
      groceryList: [
        { id: 0, text: 'Vegetables' },
        { id: 1, text: 'Cheese' },
        { id: 2, text: 'Whatever else humans are supposed to eat' }
      ]
    }
  }
}

const app = Vue.createApp(TodoList)

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})

app.mount('#todo-list-app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

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>
1
2
3
4
5
6
7

# Связь с пользовательскими элементами Web Components

Можно отметить, что компоненты Vue очень похожи на пользовательские элементы, являющиеся частью спецификации Web Components (opens new window). Синтаксис компонентов Vue намеренно следует этой спецификации. К примеру, компоненты Vue реализуют API для слотов (opens new window) и специальный атрибут is. Но есть несколько ключевых различий:

  1. Спецификация Web Components уже завершена, но реализована не во всех браузерах. Safari 10.1+, Chrome 54+ и Firefox 63+ уже поддерживают веб-компоненты. В сравнении, компоненты Vue стабильно работают во всех поддерживаемых браузерах (за исключением IE11 — подробности здесь (opens new window)). При необходимости компоненты Vue можно «обёрнуть» в нативные пользовательские элементы.
  1. Компоненты Vue предоставляют возможности, недоступные в простых пользовательских элементах. Самые важные из них: межкомпонентная передача данных, коммуникация с использованием пользовательских событий и интеграция с инструментами сборок.

Хоть Vue и не использует пользовательские элементы внутри себя, но имеет отличную интероперабельность (opens new window) если потребуется использовать или распространять в виде пользовательских элементов. Также Vue CLI поддерживает сборку компонентов Vue, которые будут регистрировать себя как нативные пользовательские элементы.

# Готовы к большему?

Пока что лишь вкратце познакомились с основными функциями ядра Vue.js — в следующих разделах руководства будем разбирать подробнее эти и другие интересные возможности, поэтому не забудьте прочитать его целиком!