Dentro de un componente que utiliza <script setup>, defineExpose() es una macro del compilador que permite exponer de forma explícita variables, funciones o incluso refs para que puedan ser accesibles desde el exterior. Esto es útil, por ejemplo, cuando queremos controlar un componente a través de una referencia (ref) en el componente padre.
)
Imagina que quieres crear un componente modal que se pueda abrir y cerrar desde un componente padre. Para ello, definiremos dos métodos: open y close, que manipulan un estado reactivo isOpen que controla la visibilidad del modal. Con defineExpose() haremos que estos métodos sean accesibles desde el exterior.
<script setup lang="ts">
import { ref } from 'vue'
const isOpen = ref(false)
const open = () => {
isOpen.value = true
}
const close = () => {
isOpen.value = false
}
defineExpose({
open,
close
})
</script>
<template>
<div
v-if="isOpen"
class="fixed inset-0 flex items-center justify-center bg-gray-800 bg-opacity-75"
>
<div class="bg-white p-6 rounded-lg shadow-lg">
<slot />
<button
class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-700"
@click="close"
>
Cerrar
</button>
</div>
</div>
</template>Plantilla (Template):
Se utiliza v-if="isOpen" para mostrar u ocultar el modal según el estado de la variable visible. Además, se define un slot para permitir la inserción de contenido personalizado y se añade un botón que cierra el modal al hacer clic.
Script Setup:
Se importa ref de Vue para crear una variable reactiva isOpen.
Se definen dos funciones, open y close, que modifican el estado del modal.
Se llama a defineExpose({ open, close }) para que estos métodos sean accesibles desde el componente padre a través de una referencia.
Para utilizar este modal, podrías tener un componente padre que lo importe y lo controle mediante una referencia:
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import MyModal from '@/components/MyModal.vue'
const myModal = useTemplateRef('myModalRef')
const handleOpenModal = () => {
myModal.value?.open()
}
</script>
<template>
<main class="flex items-center justify-center flex-col gap-4 h-screen">
<button @click="handleOpenModal">
Abrir modal
</button>
<MyModal ref="myModalRef" />
</main>
</template>En este ejemplo, al hacer clic en el botón "Abrir Modal", se invoca el método open() expuesto desde el componente Modal, lo que cambia el estado de isOpen y muestra el modal.
El uso de defineExpose() en Vue 3 con <script setup> es una herramienta poderosa que permite mantener el encapsulamiento del componente sin sacrificar la flexibilidad de exponer ciertas funcionalidades a componentes padres. Con este enfoque, es posible crear componentes modulares y reutilizables, como en el ejemplo del modal, donde los métodos open y close se pueden invocar externamente para controlar su comportamiento.