Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як викликати метод дочірнього компонента з батька і навіщо defineExpose?

Батько отримує доступ до дочірнього компонента через template ref:

<script setup>
import { useTemplateRef } from 'vue';
import VideoPlayer from './VideoPlayer.vue';

const player = useTemplateRef('player');   // Vue 3.5+; раніше - const player = ref(null)

function startOver() {
  player.value?.seek(0);
  player.value?.play();
}
</script>

<template>
  <VideoPlayer ref="player" />
  <button @click="startOver">Спочатку</button>
</template>

Але компоненти з <script setup> закриті за замовчуванням: через ref батько не бачить нічого - ні змінних, ні функцій дитини. Те, що можна викликати ззовні, дитина оголошує явно:

<!-- VideoPlayer.vue -->
<script setup>
import { useTemplateRef } from 'vue';

const video = useTemplateRef('video');

function play() { video.value.play(); }
function seek(seconds) { video.value.currentTime = seconds; }

defineExpose({ play, seek });
</script>

<template>
  <video ref="video" src="/intro.mp4"></video>
</template>

Це навмисне рішення: публічний інтерфейс компонента - props, events, slots і явно відкриті методи, а не будь-яка внутрішня змінна.

Коли виклик методу дитини доречний - імперативні дії, які погано виражаються через стан:

  • фокус на полі (input.focus()), прокрутка до елемента;
  • керування медіа (play, pause, seek);
  • відкриття модального вікна сторонньої бібліотеки, скидання форми.

Коли краще інакше: якщо батько змінює дані дитини - це props чи v-model. Виклик методів для синхронізації стану робить потік даних непрозорим: незрозуміло, хто й коли змінив стан.

Що варто знати:

  • ref заповнюється після монтування - у setup батька він ще null; звертатися в onMounted чи обробниках подій;
  • ref на компонент усередині v-if стає null, коли компонент прибрано, - звідси ?.;
  • ref у v-for дає масив екземплярів;
  • TypeScript: тип відкритого API береться з defineExpose - useTemplateRef<InstanceType<typeof VideoPlayer>>('player') чи автоматичне виведення в Vue 3.5 з Volar.

Докладніше в документації: defineExpose

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання