Události z komponenty

Položky nabídky teď mají tlačítka Objednat a objednávka je v App.vue: ref objednavka a funkce pridejDoObjednavky(id), která do ní přidá položku s tímhle id, nebo jeden kus navíc, když už tam je. Tlačítka jsou ale v PolozkaMenu a komponenta nemůže měnit data rodiče: objednavka nemá a její props jsou jen ke čtení.

Komponenta proto rodiči oznámí, že se něco stalo, a to událostí, stejně jako vám tlačítko oznamuje kliknutí událostí click. Své události deklaruje pomocí defineEmits, který vrátí funkci na jejich vysílání. Tu si uložte do proměnné emit:

<script setup>
defineProps({
    polozka: { type: Object, required: true },
});
const emit = defineEmits(["objednat"]);
</script>

<template>
    <li class="polozka">
        <span>{{ polozka.nazev }}</span>
        <button @click="emit('objednat', polozka.id)">Objednat</button>
    </li>
</template>

emit('objednat', polozka.id) vyšle (anglicky emit) událost objednat a s ní hodnotu, id položky. Rodič ji poslouchá jako každou jinou událost, pomocí @:

<PolozkaMenu v-for="polozka in nabidka" :key="polozka.id" :polozka="polozka" @objednat="pridejDoObjednavky" />

Když událost přijde, Vue zavolá pridejDoObjednavky s hodnotou události, takže id je id položky, na jejíž tlačítko se kliklo. Komponenta neví, co s tím rodič udělá. Jen řekne „tuhle položku někdo objednal“ a rodič rozhodne, co se stane.

emit funguje i ve skriptu, třeba ve funkci, kterou tlačítko zavolá. Ve skriptu jsou props v objektu, který vrací defineProps:

const props = defineProps({
    polozka: { type: Object, required: true },
});
const emit = defineEmits(["objednat"]);

function objednej() {
    emit("objednat", props.polozka.id);
}

Typické chyby:

  • Událost, kterou rodič poslouchá pod jiným jménem, třeba @objednano pro emit('objednat'), nikdy nedorazí. Nic se nestane a konzole taky nic nehlásí, takže zkontrolujte, že jména souhlasí.
  • Událost, která chybí v defineEmits, sice funguje, ale když ji komponenta vyšle, Vue varuje: [Vue warn]: Component emitted event "objednat" but it is neither declared in the emits option nor as an "onObjednat" prop. Deklarujte každou událost: seznam každému, kdo komponentu čte, řekne, co umí oznámit.

Pokyny

  1. V PolozkaMenu.vue deklarujte událost objednat a vyšlete ji s id položky, když se klikne na tlačítko Objednat.

  2. V App.vue poslouchejte událost na PolozkaMenu a obsluhujte ji funkcí pridejDoObjednavky. Objednejte jedno Cappuccino a dva Mrkvové dorty: objednávka ukáže Cappuccino ×1 a Mrkvový dort ×2.