логотип PurpleSchool
логотип PurpleSchool

Создание и использование компонентов в Vue JS

Автор

Олег Марков

Введение

Компоненты — это одна из ключевых идей Vue.js. Они позволяют разбивать интерфейс приложения на независимые, переиспользуемые части, каждая из которых логически определяет некоторую область экрана и её поведение. Благодаря компонентному подходу, ваш код становится структурированным, поддерживаемым и легче тестируется. Если вы осваиваете Vue, понимать логику создания и использования компонентов — обязательно.

В этом материале я покажу вам, как создавать компоненты в Vue, объясню основные концепты, связанные с их использованием, дам примеры кода и разберу распространённые сценарии и тонкости, с которыми вы можете столкнуться.


Что такое компонент в Vue.js

Компонент в Vue — это переиспользуемый экземпляр с собственными свойствами, данными, вычисляемыми значениями и методами. По сути, каждый компонент — это отдельный шаблон, на который "навешивается" некоторая логика.

Компоненты делятся на два основных вида:

  • Глобальные компоненты — объявляются один раз и могут использоваться в любом месте приложения.
  • Локальные компоненты — объявляются внутри другого компонента и доступны только в нем.

Основы создания компонента

Объявление компонента

В Vue.js есть несколько способов объявить компонент: через глобальную регистрацию, локальную регистрацию и с использованием однофайловых компонент (.vue-файлы, SFC).

Глобальная регистрация

Если хотите использовать компонент по всему приложению, его нужно зарегистрировать глобально. Покажу пример:

// Регистрируем компонент глобально
Vue.component('my-button', {
  template: '<button>Нажми меня!</button>' // Шаблон кнопки
})

После регистрации <my-button></my-button> можно использовать в любом шаблоне Vue-приложения.
В глобальном варианте объявлять компонент можно только до того, как создадите root Vue instance.

Локальная регистрация

Если компонент нужен только в родительском компоненте, используйте локальную регистрацию:

const MyButton = {
  template: '<button>Нажмите здесь</button>' // Определили компонент
}

new Vue({
  el: '#app',
  components: {
    'my-button': MyButton // Зарегистрировали локально
  },
  template: `
    <div>
      <my-button></my-button>
    </div>
  `
})

Компонент доступен только внутри текущего компонента.

Single File Components (SFC)

На практике большинство компонентов создаются в отдельно стоящих .vue файлах. Такой файл содержит сразу шаблон, логику и стили.

Пример файла MyButton.vue: ```vue

SFC-структуру поддерживают только сборщики вроде Vue CLI, Vite или Webpack, так что для запуска таких компонентов нужен соответствующий build-процесс.

### Структура объекта компонента

Вот что обычно можно встретить в объекте компонента:

- `template`: разметка компонента
- `data`: функция, возвращающая объект с данными
- `props`: свойства, которые компонент принимает снаружи
- `methods`: методы компонента
- `computed`: вычисляемые свойства
- `watch`: наблюдатели за изменениями данных

Посмотрите простой пример:
js Vue.component('counter', { template: `

`, data() { return { count: 0 // локальное состояние компонента } } }) ```


Связь между компонентами

Один из самых частых вопросов — как компоненты обмениваются данными. В Vue для этого придуманы props и события.

Передача данных от родителя к потомку через props

props — это способ пробрасывать данные в дочерний компонент. Смотрите:

Vue.component('hello', {
  props: ['name'], // получаем проп name
  template: '<p>Привет, {{ name }}!</p>'
})

// В шаблоне родителя:
<hello name="Денис"></hello>

Весьма удобно пробрасывать любые значения, если они объявлены в массиве props.

Типизация и значения по умолчанию

Для более явного контроля можно указать тип пропа и дефолтное значение:

props: {
  age: {
    type: Number,
    default: 18
  }
}

Это помогает поймать ошибки — если пытаетесь передать строку туда, где ожидается число, получите предупреждение в консоли.

Отправка событий от потомка к родителю

Иногда дочернему компоненту нужно передать данные "вверх". Для этого он генерирует событие через $emit:

// Сначала определим дочерний компонент
Vue.component('my-input', {
  template: '<input @input="updateValue">',
  methods: {
    updateValue(event) {
      this.$emit('input', event.target.value) // генерируем событие
    }
  }
})

// В родительском компоненте ловим событие input
<my-input @input="handlerMethod"></my-input>

$emit прокидывает любые данные вместе с событием вверх по дереву компонентов, давая родительскому компоненту возможность на них реагировать. Это стандартный паттерн Vue для обратной связи с родителем.


Переиспользуемость: слоты и динамические компоненты

Vue предлагает мощные инструменты для еще большей переиспользуемости компонентов:

Использование слотов

Слоты (<slot>) позволяют внедрять любую разметку внутрь компонента, аналогично "детям" в React:

Vue.component('card', {
  template: `
    <div class="card">
      <slot></slot> <!-- Здесь будет содержимое, переданное в компонент -->
    </div>
  `
})

Вот как это использовать:

<card>
  <h3>Заголовок карточки</h3>
  <p>Контент карточки</p>
</card>

Именованные слоты

Чтобы было несколько областей вставки, используйте именованные слоты:

<template>
  <div>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

Использование:

<custom-layout>
  <template #header>
    <h1>Заголовок</h1>
  </template>

  <p>Основной контент</p>

  <template #footer>
    <div>Подвал</div>
  </template>
</custom-layout>

Динамические компоненты

Порой нужно переключаться между разными компонентами динамически (например, табы). Для этого существует <component :is="componentName">:

<!-- переменная currentTabComponent определяет, какой компонент рендерится -->
<component :is="currentTabComponent"></component>

В JS: js data() { return { currentTabComponent: 'TabHome' // имя текущего компонента } } Vue автоматически переключает компонент по значению в :is. Удобно для построения UI на лету.


Жизненный цикл компонента

Каждый компонент в Vue проходит некие фазы жизни (создание, монтирование, обновление, уничтожение). На каждой из фаз можно "подвесить" свой код через методы жизненного цикла:

  • created — компонент создан, но еще не смонтирован в DOM
  • mounted — компонент появилось в DOM, можно обращаться к элементам шаблона
  • updated — что-то изменилось, компонент перерисовался
  • destroyed — компонент уничтожен

Полный список доступен в документации. Пример:

Vue.component('logger', {
  template: '<div>Проверьте консоль</div>',
  mounted() {
    // Вызывается после появления в DOM
    console.log('Компонент смонтирован')
  },
  destroyed() {
    console.log('Компонент удален')
  }
})

Методы жизненного цикла — мощный инструмент для "тонкой настройки" компонентов, мониторинга, подписки или очистки ресурсов.


Стилизация компонентов

Обычно в SFC можно описать стили прямо во <style>. Важно помнить:

  • Стили в SFC по умолчанию глобальные;
  • Если добавить атрибут scoped, то стили будут применяться только к этому компоненту.
<style scoped>
.button {
  background: #42b983;
}
</style>

Это предотвращает "протекание" стилей между компонентами.


Асинхронные компоненты и ленивый импорт

Vue умеет подгружать компоненты по требованию — это помогает уменьшить размер основного JS-файла.

Пример динамической загрузки:

Vue.component('async-example', () => import('./MyComponent.vue'))

Компонент загрузится только в момент рендера, когда действительно понадобится, а не сразу при загрузке всего приложения.


Формы, валидация и управление состоянием

Обычно формы (input, select и пр.) выносят в отдельные компоненты, используя двухстороннюю привязку и слоты.

Пример:

<template>
  <input :value="value" @input="$emit('input', $event.target.value)">
</template>
<script>
export default {
  props: ['value']
}
</script>

Такой подход позволяет использовать компонент с v-model:

<my-input v-model="username"></my-input>

Ваши компоненты становятся полностью совместимыми с основными средствами управления состоянием Vue.


Практика: создание комплексного компонента

Давайте разберём реальный пример — карточка товара с кнопкой "Купить".

ProductCard.vue: ```vue


В родительском компоненте вы используете карточку так:
vue
Обратите внимание, как через `@buy` родительский компонент реагирует на действие пользователя, а через слот добавляет собственный footer.

---

## Ленивая загрузка и оптимизация производительности

Vue поддерживает стратегию code splitting — это значит, что тяжёлые и редко используемые компоненты можно грузить динамически:
js components: { LazyComponent: () =

import('./HeavyComponent.vue') } ```

А совмещая с динамическим <component :is="...">, можно реализовать прогрессивную загрузку отдельных экранов.


Использование именованных компонентов и alias

Иногда один и тот же компонент удобно перерегистрировать под разными именами для разных целей интерфейса:

import MyButton from './Button.vue'
export default {
  components: {
    'form-button': MyButton,
    'modal-button': MyButton
  }
}

Это полезно, чтобы разграничить роли кнопок или применять разные стили.


Взаимодействие между sibling-компонентами (сестринские компоненты)

Если родитель напрямую не участвует в обмене данных, можно использовать event-bus или Vuex, либо, для простых приложений, поднимать общее состояние выше по дереву.


Заключение

Работа с компонентами — фундаментальный навык в Vue.js. Они позволяют делать код модульным, повторно использовать UI-элементы, просто управлять состоянием и выстраивать архитектуру приложения любого масштаба.
Читайте официальную документацию, экспериментируйте с SFC, слотами, жизненным циклом и динамическими компонентами — Vue разработан так, чтобы сделать создание сложных интерфейсов проще и приятнее.


Частозадаваемые технические вопросы по теме статьи и ответы на них

Как пробросить методы из родителя в дочерний компонент напрямую?

В прямом варианте методы не пробрасываются как props. Но вы можете передать функцию как проп и вызвать её внутри дочернего компонента:

// Родительский компонент
<child :onAction="myParentMethod"></child>

// Дочерний
props: { onAction: Function }
methods: {
  clickHandler() {
    this.onAction()
  }
}

Такой подход позволит дочернему компоненту вызывать родительскую функцию через переданный проп.

Как передать несколько значений через props, не перечисляя каждый в шаблоне явным образом?

Можно использовать привязку объекта:

const obj = {title: 'Имя', desc: 'Описание'}
<my-component v-bind="obj" />

Все ключи объекта будут соответствовать props в компоненте.

Как обновлять props изнутри дочернего компонента?

Props считаются "read-only" — их нельзя изменять напрямую. Если нужно "отдать" новое значение наверх, используйте событие $emit и двустороннюю привязку через .sync или v-model.

this.$emit('update:propName', updatedValue)

Родитель должен обработать и изменить значение.

Как зарегистрировать компонент только в одном определённом месте приложения?

Регистрируйте его как локальный компонент в нужном компоненте (например, внутри компонента страницы или layout). Глобальная регистрация не требуется.

Как использовать mixins для совместного использования логики в нескольких компонентах?

Определите объект mixin с нужными методами и данными, затем подключите в каждый компонент:

const myMixin = { data() { return { value: 1 } }, methods: { doSomething() {} } }

export default {
  mixins: [myMixin]
}

Это объединит опции миксина с текущим компонентом.

Стрелочка влевоКак работает компиляция Vue CoreОбработка кликов и пользовательских событий в VueСтрелочка вправо

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueИнструкция по установке и компонентам Vue sliderРабота с таблицами во Vue через TanStackУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий