Что такое defineExpose во Vue 3

Ответ

defineExpose — это функция в Vue 3 Composition API, которая позволяет явно указать, какие свойства или методы компонента должны быть доступны извне через ref.

По умолчанию, в <script setup> все переменные и методы инкапсулированы. Если нужно, чтобы родительский компонент мог их использовать, их нужно "экспонировать".

Пример:

<script setup>
import { ref } from 'vue';

const internalValue = ref('Секретно');
const publicMethod = () => alert('Доступно снаружи!');

defineExpose({
  publicMethod,
  value: internalValue
});
</script>

Родительский компонент:

<template>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
const childRef = ref(null);

onMounted(() => {
  childRef.value.publicMethod(); // Работает
  console.log(childRef.value.value); // 'Секретно'
});
</script>

Без defineExpose доступ к internalValue и publicMethod был бы невозможен.

Ответ 18+ 🔞

А, ну вот, слушай, смотри, сейчас объясню про эту defineExpose. Это же, блядь, как замок на двери в твоей приватной хате!

Представь: ты пишешь компонент на <script setup>. Всё, что там внутри — это твоё личное дело, твой внутренний бардак. Переменные, функции, всякая хуйня — они там, как в бункере, сидят. Снаружи, из родительского компонента, нихуя не видно, даже если ты через ref на этот компонент нацелился.

А потом тебе вдруг надо: «Эй, родитель, вот эту функцию можешь вызвать!» Или: «Вот эту переменную можешь почитать!». А как? Дверь-то на замке!

Вот тут и появляется наш спаситель — defineExpose. Это как окошко в твоём бункере, через которое ты можешь высунуть наружу ровно то, что хочешь. Всё остальное — остаётся внутри, в тайне.

Смотри, как это выглядит:

<script setup>
import { ref } from 'vue';

// Это наше секретное оружие, внутри компонента
const secretSauce = ref('Рецепт борща от бабушки');
// А это наша публичная дурацкая кнопка
const publicAlert = () => alert('Не трогай меня!');

// И вот мы говорим: "Окей, мир, вот тебе две вещи, остальное — нахуй не лезь"
defineExpose({
  publicAlert,
  sauce: secretSauce // Можем даже под псевдонимом выдать
});
</script>

А теперь родитель, этот всезнайка, подключается:

<template>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
const childRef = ref(null); // Создаём ссылку на ребёнка

onMounted(() => {
  // Теперь можем тыкать в то, что выставили наружу
  childRef.value.publicAlert(); // Вызовет алерт — работает!
  console.log(childRef.value.sauce); // Выведет 'Рецепт борща от бабушки'
  // А попробуй до secretSauce добраться — нихуя! undefined, ошибка, пиздец.
});
</script>

Вот и вся магия, ёпта. Без defineExpose родитель смотрит на твой компонент как баран на новые ворота — видит оболочку, а внутрь попасть не может. А с ним — только то, что сам разрешил. Удобная же штука, а? Чистая контролируемая утечка данных, а не какой-то пиздец!