Composition API: setup()
Uso básico
El hook setup()
sirve como el punto de entrada para el uso de Composition API, en los componentes en los siguientes casos:
- Uso de Composition API sin un paso de compilación;
- Cuando se integra código basado en Composition API en un componente que usa Options API.
Nota
El uso de <script setup>
está fuertemente recomendado si está utilizando Composition API (la Composition API) con Componentes de un Solo Archivo (SFC), de esta manera se obtiene una sintaxis mas sucinta y ergonómica
Podemos declarar el estado reactivo usando Reactivity APIs y exponerlos a la plantilla devolviendo un objeto desde setup()
. Las propiedades del objeto devuelto también estarán disponibles en la instancia del componente (si otras opciones son usadas):
vue
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
// expone a la plantilla y otros hooks de las opciones de la API
return {
count
}
},
mounted() {
console.log(this.count) // 0
}
}
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
Ten en cuenta que las referencias (refs) devueltas por setup
son automáticamente shallow unwrapped cuando son accedidas en la plantilla, por lo que no necesitas utilizar .value
cuando se acceden a ellas. También se desenvuelven de la misma manera cuando se accede a this
.
:::consejo El propio setup()
no tiene acceso a la instancia del componente - this
tendrá un valor de undefined
dentro de setup()
. Puedes acceder a los valores expuestos por la Composition-API desde la Options API, pero no al revés. :::
Accediendo a las propiedades (props)
El primer argumento de la función setup
es el argumento props
. Tal y como se espera en un componente estándar, las props
dentro de una función setup
son reactivas y se actualizarán cuando se pasen nuevas propiedades.
js
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
Tenga en cuenta que si desestructura el objeto props
, las variables desestructuradas perderán reactividad. Por lo tanto, se recomienda acceder siempre a a los props en forma de props.xxx
.
Si realmente necesita desestructurar los props, o necesita pasar una propiedad a una función externa mientras conserva la reactividad, puede hacerlo con las APIs de utilidad toRefs() y toRef():
js
import { toRefs, toRef } from 'vue'
export default {
setup(props) {
// convierte `props` en un objeto de refs, luego desestructura
const { title } = toRefs(props)
// `title` es una referencia que vigila a `props.title`
console.log(title.value)
// O bien, convertir una sola propiedad de `props` en una ref
const title = toRef(props, 'title')
}
}
El Contexto en Setup
El segundo argumento que se pasa a la función setup
es un objeto Contexto de configuración. El objeto contexto expone otros valores que pueden ser útiles dentro de setup
:
js
export default {
setup(props, context) {
// Atributos (objeto no reactivo, equivalente a $attrs)
console.log(context.attrs)
// Slots (objeto no reactivo, equivalente a $slots)
console.log(context.slots)
// Emitir eventos (Función, equivalente a $emit)
console.log(context.emit)
// Exponer propiedades públicas (Función)
console.log(context.expose)
}
}
El objeto de contexto no es reactivo y puede ser desestructurado con seguridad:
js
export default {
setup(props, { attrs, slots, emit, expose }) {
...
}
}
Las propiedades attrs
y slots
son objetos con estado que siempre son actualizados cuando el mismo componente es actualizado. Esto significa que debes evitar desestructurarlos y siempre referenciar las propiedades como attrs.x
o slots.x
. Ten en cuenta también que, a diferencia de props
, las propiedades de attrs
y slots
no son reactivas. Si pretendes aplicar efectos secundarios basados en los cambios de attrs
o slots
, debes hacerlo dentro de un hook del ciclo de vida onBeforeUpdate
.
Exponiendo Propiedades Públicas
expose
es una función que puede utilizarse para limitar explícitamente las propiedades expuestas cuando la instancia del componente es accedida por un componente padre a través de refs de la Plantilla :
js
export default {
setup(props, { expose }) {
// hacer la instancia "cerrada" -
// ej. no exponer nada al padre
expose()
const publicCount = ref(0)
const privateCount = ref(0)
// exponer de forma selectiva el estado local
expose({ count: publicCount })
}
}
Uso con Funciones de Renderizado
setup
también puede devolver una función de renderizado que puede hacer uso directamente del estado reactivo declarado en el mismo ámbito:
js
import { h, ref } from 'vue'
export default {
setup() {
const count = ref(0)
return () => h('div', count.value)
}
}
Devolver una función de renderizado nos previene devolver cualquier otra cosa. Internamente esto no debería ser un problema, pero puede ser problemático si queremos exponer métodos de este componente al componente padre a través de las refs. de la plantilla.
Podemos resolver este problema llamando a expose()
:
js
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0)
const increment = () => ++count.value
expose({
increment
})
return () => h('div', count.value)
}
}
El método incremento
estaría entonces disponible en el componente padre a través de una plantilla de referencia.