Composition API: setup()
Základní použití
V následujících případech slouží hook setup()
jako vstupní bod pro použití Composition API v komponentách:
- Použití Composition API bez build fáze;
- Integrace s kódem založeným na Composition API v komponentě s Options API.
Poznámka
Pokud používáte Composition API v Single-File komponentách (SFC), silně se doporučuje použít <script setup>
pro stručnější a ergonomičtější syntaxi.
Pomocí Reaktivního API můžeme deklarovat reaktivní stav a vystavit jej šabloně návratem v objektu ze setup()
. Vlastnosti vráceného objektu budou na instanci komponenty také dostupné (pokud jsou použity jiné vlastnosti):
vue
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
// vystavit šabloně a dalším možnostem Options API
return {
count
}
},
mounted() {
console.log(this.count) // 0
}
}
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
refs vrácené ze setup
jsou při přístupu ze šablony automaticky rozbaleny, takže nemusíte pro přístup k hodnotám používat .value
. Stejným způsobem jsou rozbaleny při přístupu přes this
.
Samotný setup()
nemá přístup k instanci komponenty - this
bude mít uvnitř setup()
hodnotu undefined
. Z Options API můžete přistupovat k hodnotám vystaveným Composition API, ale ne naopak.
setup()
by měl synchronně vrátit objekt. Jediný případ, kdy může být použito async setup()
, je když je komponenta potomkem komponenty Suspense.
Přístup k vlastnostem (props)
Prvním parametrem v funkci setup
je objekt props
. Stejně jako byste očekávali v běžné komponentě, props
uvnitř funkce setup
jsou reaktivní a budou při předání nových vlastností aktualizovány.
js
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
Všimněte si, že pokud destrukturujete objekt props
, destrukturované proměnné ztratí reaktivitu. Proto se doporučuje k props vždy přistupovat ve formě props.xxx
.
Pokud skutečně potřebujete props destrukturovat nebo je předat do externí funkce a zachovat reaktivitu, můžete to udělat pomocí utilitních API toRefs() a toRef():
js
import { toRefs, toRef } from 'vue'
export default {
setup(props) {
// převede `props` na objekt složený z refs a poté destrukturuje
const { title } = toRefs(props)
// `title` je ref, který sleduje `props.title`
console.log(title.value)
// NEBO, převede jednu vlastnost z `props` na ref
const title = toRef(props, 'title')
}
}
Setup Context
Druhý parametr předaný do funkce setup
je objekt Setup Context. Kontextový objekt poskytuje další hodnoty, které mohou být uvnitř setup
užitečné:
js
export default {
setup(props, context) {
// Atributy (ne-reaktivní objekt, ekvivalent k $attrs)
console.log(context.attrs)
// Sloty (ne-reaktivní objekt, ekvivalent k $slots)
console.log(context.slots)
// Vysílání událostí (funkce, ekvivalent k $emit)
console.log(context.emit)
// Vystavení veřejných vlastností (funkce)
console.log(context.expose)
}
}
Kontextový objekt není reaktivní a může být bezpečně destrukturován:
js
export default {
setup(props, { attrs, slots, emit, expose }) {
...
}
}
attrs
a slots
jsou objekty se stavem, které jsou vždy aktualizovány, když je aktualizována samotná komponenta. To znamená, že byste se měli vyhnout destrukturování a vždy odkazovat na vlastnosti jako attrs.x
nebo slots.x
. Také si zapamatujte, že na rozdíl od props
jsou vlastnosti attrs
a slots
nereaktivní. Pokud plánujete provádět vedlejší efekty na základě změn v attrs
nebo slots
, měli byste tak činit uvnitř lifecycle hooku onBeforeUpdate
.
Vystavení veřejných vlastností
expose
je funkce, která se používá k explicitnímu omezení vystavených vlastností, když je instance komponenty přistupována komponentou rodiče pomocí template refs:
js
export default {
setup(props, { expose }) {
// udělat instanci "uzavřenou" -
// tj. do rodiče nevystavit nic
expose()
const publicCount = ref(0)
const privateCount = ref(0)
// selektivně vystavit lokální stav
expose({ count: publicCount })
}
}
Použití s funkcemi pro vykreselní
setup
může také vrátit funkci pro vykreslení, která může přímo využívat reaktivní stav deklarovaný ve stejném rozsahu (scope):
js
import { h, ref } from 'vue'
export default {
setup() {
const count = ref(0)
return () => h('div', count.value)
}
}
Vrácení funkce pro vykreslení nám zabrání vrátit cokoli jiného. Interně by to nemělo vadit, ale může to být problematické, pokud chceme vystavit metody této komponenty do komponenty rodiče pomocí template refs.
Tento problém můžeme vyřešit voláním 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)
}
}
Metoda increment
bude pak dostupná v komponentně rodiče pomocí template ref.