Sdílený stav

Až dosud data, která potřebovalo několik komponent, patřila jejich rodiči: ten je předal dolů pomocí props a děti si o změny řekly událostmi, jako v lekci Události komponent. Pro rodiče a jeho děti je to správná cesta. Některá data ale potřebuje celá aplikace: objednávku, přihlášeného uživatele, košík v e-shopu. Předávat je dolů přes všechny komponenty mezi nimi je zdlouhavé.

Jde to jednodušeji: dejte ref do samostatného modulu, mimo jakoukoli funkci, a k němu funkce, které ho mění:

import { ref } from "vue";

export const objednavka = ref([]);

export function pridejDoObjednavky(polozka) {
    const nalezeny = objednavka.value.find((radek) => radek.id === polozka.id);
    if (nalezeny) {
        nalezeny.pocet++;
    } else {
        objednavka.value.push({ ...polozka, pocet: 1 });
    }
}

Každá komponenta, která objednávku potřebuje, si importuje, co používá:

<script setup>
import { objednavka } from "./objednavka.js";
</script>

<template>
    <p>Objednaných položek: {{ objednavka.length }}</p>
</template>

Funguje to, protože modul proběhne jen jednou. První import spustí objednavka.js a vytvoří ref, každý další import dostane tentýž ref. Když tedy PolozkaMenu.vue zavolá pridejDoObjednavky(), přidá do přesně té objednávky, kterou ukazuje Objednavka.vue, a Vue seznam aktualizuje, jako po každé změně refu.

Porovnejte to s composable: tam je ref() uvnitř funkce, a tak každé volání vytvoří nový ref a každá komponenta má svůj. Tady je ref() venku, a tak je jen jeden, který sdílejí všechny komponenty. Rozdíl dělá stejný řádek na jiném místě.

Funkce, které sdílený stav mění, mějte hned u něj, ve stejném modulu, jako je pridejDoObjednavky(). Pak vždycky víte, kde se objednávka mění: ať se mění kdekoli, je to přes jednu z nich.

Ve větších aplikacích se sdílený stav obvykle dává do knihovny Pinia od autorů Vue. Funguje na stejném principu a přidává nástroje na hledání chyb. Potkáte ji po tomto kurzu.

Pokyny

  1. Zprovozněte tlačítka Objednat. V PolozkaMenu.vue importujte pridejDoObjednavky z ./objednavka.js a po kliknutí na tlačítko ji zavolejte s položkou. V Objednavka.vue importujte objednavka z ./objednavka.js místo prázdného pole. Objednejte si dvakrát espresso: seznam ukáže 2 × Espresso.

  2. Přidejte možnost řádek odebrat. V objednavka.js napište a exportujte odeberZObjednavky(id), která pomocí filter() nechá jen řádky s jiným id. V Objednavka.vue přidejte ke každému řádku tlačítko ×, které ji zavolá.

  3. Ukažte v App.vue pod nadpisem celkovou cenu objednávky: Celkem: 195 Kč. V objednavka.js exportujte vypočítanou hodnotu celkem, která v cyklu sečte cena * pocet všech řádků, a v App.vue ji importujte.