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

Что такое компонент?

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

Vue.js делает работу с компонентами настолько простой, что вы удивитесь, как вы вообще жили без них до этого. Но давайте начнём с самого простого.

Создание первого компонента

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

Вот пример простого компонента кнопки:

<template>
  <button>{{ label }}</button>
</template>

<script setup>
const props = defineProps({
  label: {
    type: String,
    required: true
  }
});
</script>

Здесь у нас компонент кнопки, который принимает пропс label — это текст, который будет отображаться внутри кнопки. Теперь давайте подключим этот компонент в родительском компоненте и передадим ему текст:

<template>
  <MyButton label="Нажми меня" />
</template>

<script setup>
import MyButton from './components/MyButton.vue';
</script>

Простой компонент уже готов к использованию. Мы его импортировали и использовали, как обычный HTML-тег, но с гораздо большей гибкостью. И что самое классное — таких компонентов у вас может быть сколько угодно. Vue позволяет вам не только переиспользовать их, но и делать это максимально удобно.

Важность пропсов

Компоненты в Vue могут принимать пропсы (props) — это данные, которые вы передаёте из родительского компонента в дочерний. Пропсы позволяют сделать компоненты гибкими. Например, та же кнопка может иметь разные лейблы, стили, размеры — всё это можно передавать через пропсы.

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

<template>
  <button :class="sizeClass">{{ label }}</button>
</template>

<script setup>
const props = defineProps({
  label: {
    type: String,
    required: true
  },
  size: {
    type: String,
    default: 'medium'
  }
});

const sizeClass = computed(() => {
  return {
    small: 'btn-small',
    medium: 'btn-medium',
    large: 'btn-large'
  }[props.size];
});
</script>

<style>
.btn-small {
  font-size: 12px;
  padding: 5px 10px;
}
.btn-medium {
  font-size: 16px;
  padding: 10px 20px;
}
.btn-large {
  font-size: 20px;
  padding: 15px 30px;
}
</style>

Теперь наш компонент кнопки поддерживает разные размеры. Мы добавили проп size, который по умолчанию равен «medium», но его можно изменить, передав другие значения.

<template>
  <MyButton label="Кнопка маленькая" size="small" />
  <MyButton label="Кнопка большая" size="large" />
</template>

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

События в компонентах

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

Для этого нам нужно использовать директиву v-on или сокращение @ для подписки на события:

<template>
  <button @click="handleClick">{{ label }}</button>
</template>

<script setup>
const props = defineProps({
  label: String
});

const emit = defineEmits(['click']);

const handleClick = () => {
  emit('click');
};
</script>

Теперь, когда пользователь нажмёт на кнопку, событие будет отправлено родителю:

<template>
  <MyButton label="Нажми меня" @click="handleClick" />
</template>

<script setup>
const handleClick = () => {
  alert('Кнопка нажата!');
};
</script>

Компоненты становятся интерактивными и могут информировать родительский компонент о том, что произошло какое-то действие. Это очень полезно при работе с формами, модальными окнами, табами и другими интерактивными элементами.

Слоты — секретная сила компонентов

Ещё одной мощной возможностью Vue-компонентов являются слоты. Слоты позволяют передавать в компонент произвольный HTML-код, и это делает компоненты ещё более гибкими. Это особенно полезно, если вы создаёте компонент, который должен отображать контент, переданный родительским компонентом.

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

<template>
  <div class="card">
    <header>{{ title }}</header>
    <div class="content">
      <slot></slot>
    </div>
  </div>
</template>

<script setup>
const props = defineProps({
  title: String
});
</script>

<style>
.card {
  border: 1px solid #ddd;
  padding: 20px;
}
</style>

Теперь мы можем использовать этот компонент так:

<template>
  <Card title="Заголовок карточки">
    <p>Это содержимое карточки.</p>
    <button>Кнопка внутри карточки</button>
  </Card>
</template>

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

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

Дальше мы рассмотрим тему продвинутых компонентов.


Warning: Undefined variable $aff_bottom_mark in /sites/codelab.pro/wp-content/themes/myTheme/dist/partials/post/post_base.php on line 81

Warning: Undefined variable $aff_bottom_info in /sites/codelab.pro/wp-content/themes/myTheme/dist/partials/post/post_base.php on line 85