18 gru 2025·7 min czytania

Zarządzanie stanem w Vue 3 dla paneli admina: Pinia kontra lokalny stan

Zarządzanie stanem w Vue 3 dla paneli administracyjnych: wybierz między Pinia, provide/inject i stanem lokalnym na przykładach filtrów, wersji roboczych i kart edycyjnych.

Zarządzanie stanem w Vue 3 dla paneli admina: Pinia kontra lokalny stan

Co sprawia, że stan w panelach administracyjnych jest trudny

Panele administracyjne wydają się pełne stanu, bo na jednym ekranie skupia się wiele ruchomych części. Tabela to nie tylko dane — to też sortowanie, filtry, paginacja, zaznaczone wiersze i kontekst „co się właśnie stało?”, na którym polegają użytkownicy. Dodaj długie formularze, uprawnienia zależne od roli i akcje, które zmieniają to, co UI powinno pozwalać, a drobne decyzje dotyczące stanu zaczynają mieć znaczenie.

Wyzwanie nie polega na przechowywaniu wartości. Chodzi o zachowanie przewidywalności, gdy kilka komponentów potrzebuje tej samej prawdy. Jeśli filtr pokazuje „Aktywni”, tabela, URL i akcja eksportu powinny się zgadzać. Jeśli użytkownik edytuje rekord i przechodzi gdzie indziej, aplikacja nie powinna cicho gubić jego pracy. Jeśli otworzy dwie karty, jedna nie powinna nadpisać drugiej.

W Vue 3 zwykle kończysz, wybierając jedno z trzech miejsc do przechowywania stanu:

  • Lokalny stan komponentu: należy do jednego komponentu i można go bezpiecznie zresetować przy odmontowaniu.
  • provide/inject: współdzielony stan ograniczony do strony lub obszaru funkcji, bez drążenia propsów.
  • Pinia: współdzielony stan, który musi przetrwać nawigację, być używany między trasami i łatwy do debugowania.

Przydatny sposób myślenia: dla każdego kawałka stanu zdecyduj, gdzie powinien żyć, żeby pozostał poprawny, nie zaskakiwał użytkownika i nie stał się spaghetti.

Poniższe przykłady dotyczą trzech częstych problemów w panelach admina: filtry i tabele (co powinno przetrwać a co się resetuje), wersje robocze i niezapisane edycje (formularze, którym można zaufać) oraz edycja w wielu kartach (uniknięcie kolizji stanu).

Prosty sposób klasyfikacji stanu przed wyborem narzędzia

Spory o stan stają się prostsze, gdy przestaniesz dyskutować o narzędziach i najpierw nazwiesz rodzaj stanu. Różne typy stanu zachowują się inaczej, a ich mieszanie tworzy dziwne błędy.

Praktyczny podział:

  • UI state: przełączniki, otwarte dialogi, zaznaczone wiersze, aktywne karty, kolejność sortowania.
  • Server state: odpowiedzi z API, flagi ładowania, błędy, czas ostatniego odświeżenia.
  • Form state: wartości pól, błędy walidacji, flagi dirty, niezapisane wersje robocze.
  • Cross-screen state: wszystko, co wiele tras musi czytać lub zmieniać (aktualne workspace, współdzielone uprawnienia).

Następnie zdefiniuj zakres. Zapytaj, gdzie stan jest używany dziś, a nie gdzie może być użyty kiedyś. Jeśli liczy się tylko w jednym komponencie tabeli, zwykle wystarczy lokalny stan. Jeśli dwa rodzeńcze komponenty na tej samej stronie go potrzebują, prawdziwy problem to współdzielenie na poziomie strony. Jeśli wiele tras potrzebuje tego stanu, to już obszar współdzielonego stanu aplikacji.

Kolejna kwestia to czas życia. Część stanu powinna się resetować po zamknięciu draweru. Inna część powinna przetrwać nawigację (filtry, gdy wchodzisz w rekord i wracasz). Jeszcze inna powinna przetrwać odświeżenie (długa wersja robocza, do której użytkownik wróci później). Traktowanie tych trzech tak samo prowadzi do filtrów, które tajemniczo się resetują, lub do wersji roboczych, które znikają.

Na koniec sprawdź konkurencję. Panele admina szybko trafiają na przypadki brzegowe: użytkownik otwiera ten sam rekord w dwóch kartach, tło odświeża wiersz, kiedy formularz jest brudny, albo dwaj edytorzy wyścigują się przy zapisie.

Przykład: ekran „Użytkownicy” z filtrami, tabelą i drawerem do edycji. Filtry to UI state o czasie życia strony. Wiersze to server state. Pola drawera to form state. Jeśli ten sam użytkownik jest edytowany w dwóch kartach, potrzebna jest decyzja o konkurencji: blokować, scalać czy ostrzegać.

Kiedy potrafisz oznaczyć stan według typu, zakresu, czasu życia i konkurencji, wybór narzędzia (lokalny stan, provide/inject lub Pinia) zwykle staje się jasny.

Jak wybrać: proces decyzyjny, który działa

Dobre wybory dotyczące stanu zaczynają się od jednego nawyku: opisz stan prostymi słowami, zanim wybierzesz narzędzie. Panele admina mieszają tabele, filtry, duże formularze i nawigację między rekordami, więc nawet „mały” stan może łatwo stać się źródłem błędów.

5-etapowy proces decyzyjny

  1. Kto potrzebuje tego stanu?

    • Jeden komponent: trzymaj lokalnie.
    • Kilka komponentów pod jedną stroną: rozważ provide/inject.
    • Wiele tras: rozważ Pinia.

    Filtry są dobrym przykładem. Jeśli dotyczą tylko jednej tabeli, lokalny stan wystarczy. Jeśli filtry są w nagłówku, a sterują tabelą poniżej, współdzielenie na poziomie strony (często provide/inject) utrzymuje porządek.

  2. Jak długo musi żyć?

    • Jeśli może zniknąć przy odmontowaniu, lokalny stan jest idealny.
    • Jeśli musi przetrwać zmianę trasy, Pinia zwykle lepiej pasuje.
    • Jeśli musi przetrwać reload, potrzebujesz też persystencji (storage), niezależnie od miejsca przechowywania.

    To jest szczególnie ważne dla wersji roboczych. Niezapisane edycje są wrażliwe na zaufanie: użytkownicy oczekują, że wersja robocza nadal będzie, gdy klikną i wrócą.

  3. Czy powinno to być współdzielone między kartami przeglądarki, czy izolowane per karta?

    Edycja w wielu kartach to miejsce, gdzie chowają się błędy. Jeśli każda karta powinna mieć własną wersję roboczą, unikaj jednego globalnego singletonu. Lepiej kluczować stan po ID rekordu albo trzymać go na poziomie strony, żeby jedna karta nie nadpisywała drugiej.

  4. Wybierz najprostsze rozwiązanie, które pasuje.

    Zacznij od lokalnego. Przenieś wyżej tylko wtedy, gdy poczujesz prawdziwy ból: prop drilling, zduplikowana logika lub trudne do odtworzenia resety.

  5. Potwierdź potrzeby debugowania.

    Jeśli potrzebujesz przejrzystego, przeglądalnego widoku zmian między ekranami, Pinia z centralnymi akcjami i inspekcją stanu może oszczędzić godziny. Jeśli stan jest krótkotrwały i oczywisty, lokalny stan jest łatwiejszy do ogarnięcia.

Lokalny stan komponentu: kiedy wystarcza

Lokalny stan to domyślne rozwiązanie, gdy dane są istotne tylko dla jednego komponentu na jednej stronie. Łatwo pominąć tę opcję i przeinwestować w store, którym spędzisz miesiące na utrzymaniu.

Jasnym dopasowaniem jest pojedyncza tabela z własnymi filtrami. Jeśli filtry dotyczą tylko tej tabeli (np. lista Użytkowników) i nic innego od nich nie zależy, trzymaj je jako ref w komponencie tabeli. To samo dotyczy małego stanu UI typu „czy modal jest otwarty?”, „który wiersz jest edytowany?” czy „które elementy są teraz zaznaczone?”.

Staraj się nie przechowywać tego, co możesz obliczyć. Badge „Aktywnych filtrów (3)” powinien być wyliczany z bieżących wartości filtrów. Etykiety sortowania, sformatowane podsumowania i flagi „można zapisać” też lepiej robić jako computed, bo pozostają zsynchronizowane automatycznie.

Zasady resetowania mają większe znaczenie niż samo narzędzie. Zdecyduj, co czyści się przy zmianie trasy (zwykle wszystko), a co zostaje, gdy użytkownik przełącza widoki wewnątrz tej samej strony (np. możesz zachować filtry, ale czyścić tymczasowe zaznaczenia, żeby uniknąć niechcianych akcji masowych).

Lokalny stan zwykle wystarcza, gdy:

  • Stan dotyczy jednego widgetu (jeden formularz, jedna tabela, jeden modal).
  • Żaden inny ekran nie musi go czytać ani zmieniać.
  • Możesz utrzymać go w 1–2 komponentach bez przekazywania propsów przez wiele warstw.
  • Potrafisz opisać regułę resetu w jednym zdaniu.

Głównym ograniczeniem jest głębokość. Gdy zaczynasz przewlekać ten sam stan przez wiele zagnieżdżonych komponentów, lokalny stan zmienia się w prop drilling — i to zazwyczaj sygnał, żeby przejść do provide/inject lub store.

provide/inject: współdzielenie stanu w ramach strony lub obszaru funkcji

Zachowaj Pinia dla wspólnych potrzeb
Zdobądź prawdziwy kod źródłowy i wdrażaj wzorce Pinia tam, gdzie stan musi być współdzielony między trasami.
Generuj kod

provide/inject plasuje się między lokalnym stanem a pełnym storem. Rodzic „providuje” wartości dla wszystkiego pod sobą, a zagnieżdżone komponenty „injectują” je bez przekazywania propsów. W panelach admina to świetne rozwiązanie, gdy stan należy do jednego ekranu lub obszaru funkcji, a nie do całej aplikacji.

Częsty wzorzec to szkielet strony, który posiada stan, a mniejsze komponenty go konsumują: pasek filtrów, tabela, toolbar akcji masowych, drawer z detalami i banner „nies zapisane zmiany”. Szkielet może providować małą reaktywną powierzchnię jak obiekt filters, obiekt draftStatus (dirty, saving, error) oraz kilka flag tylko do odczytu (np. isReadOnly na podstawie uprawnień).

Co providować (trzymaj to małe)

Jeśli providujesz wszystko, w zasadzie odtwarzasz store z mniejszą strukturą. Dostarczaj tylko to, czego naprawdę potrzebuje kilka dzieci. Filtry to klasyczny przykład: gdy tabela, chipsy, akcja eksportu i paginacja muszą trzymać się w zgodzie, lepiej mieć jedno źródło prawdy niż żonglować propsami i eventami.

Jasność i pułapki

Największe ryzyko to ukryte zależności: dziecko „po prostu działa”, bo coś wyżej je providuje, a potem trudno powiedzieć, skąd biorą się aktualizacje. Żeby zachować czytelność i testowalność, nadaj wstrzyknięciom jasne nazwy (często konstanta lub Symbol). Lepiej providować akcje, a nie tylko mutowalne obiekty. Małe API typu setFilter, markDirty i resetDraft jasno pokazuje właściciela i dozwolone zmiany.

Pinia: współdzielony stan i przewidywalne aktualizacje między ekranami

Od prototypu do wdrożenia
Wdróż do AppMaster Cloud lub na własny cloud bez przebudowy struktury aplikacji.
Wdróż aplikację

Pinia świeci, gdy ten sam stan musi być spójny między trasami i komponentami. W panelu admina zwykle chodzi o aktualnego użytkownika, jego uprawnienia, wybrane workspace oraz ustawienia aplikacji. To staje się uciążliwe, jeśli każdy ekran implementuje to osobno.

Store pomaga, bo daje jedno miejsce do odczytu i aktualizacji współdzielonego stanu. Zamiast przekazywać propsy przez wiele warstw, importujesz store tam, gdzie go potrzebujesz. Kiedy przechodzisz z listy do widoku detalu, reszta UI może reagować na te same wybrane ustawienia.

Dlaczego Pinia jest łatwiejszy w utrzymaniu

Pinia narzuca prostą strukturę: state dla surowych wartości, getters dla wartości pochodnych i actions dla aktualizacji. W UI admina ta struktura zapobiega „szybkim naprawom”, które zmieniają się w rozproszone mutacje.

Jeśli canEditUsers zależy od roli i feature flagi, umieść regułę w getterze. Jeśli zmiana workspace wymaga wyczyszczenia cache i przeładowania nawigacji, zrób to w action. Mniej tajemniczych watcherów i mniej pytań „dlaczego to się zmieniło?”.

Pinia dobrze współpracuje z Vue DevTools. Gdy pojawia się błąd, łatwiej sprawdzić stan store i zobaczyć, która akcja go uruchomiła, niż ścigać się za zmianami w przypadkowych reaktywnych obiektach tworzonych w losowych komponentach.

Unikaj składowania wszystkiego w store

Globalny store na początku wydaje się porządny, ale potem staje się szufladą na wszystko. Dobre kandydatury do Pinia to naprawdę współdzielone sprawy jak tożsamość użytkownika i uprawnienia, wybrany workspace, feature flagi i dane referencyjne używane w wielu ekranach.

Troski page-only (jak tymczasowe wejście w jednym formularzu) powinny pozostać lokalne, chyba że naprawdę wiele tras ich potrzebuje.

Przykład 1: filtry i tabele bez zamieniania wszystkiego w store

Wyobraź sobie stronę Orders: tabela, filtry (status, zakres dat, klient), paginacja i panel podglądu wybranego zamówienia. To szybko się komplikuje, bo kusi, by wstawić wszystkie filtry i ustawienia tabeli do globalnego store.

Proste rozumowanie: zdecyduj, co ma być pamiętane i gdzie:

  • Pamięć tylko (lokalnie lub provide/inject): reset przy opuszczeniu strony. Dobre dla stanu jednorazowego.
  • Parametry zapytania (query params): możliwe do udostępnienia i przetrwają reload. Dobre dla filtrów i paginacji, które ludzie kopiują.
  • Pinia: przetrwa nawigację. Dobre, jeśli użytkownik chce „wrócić do listy dokładnie tak, jak ją zostawił”.

Stąd implementacja zwykle idzie tak:

Jeśli nikt nie oczekuje, że ustawienia przetrwają nawigację, trzymaj filters, sort, page i pageSize w komponencie strony Orders i niech ta strona wywołuje fetch. Jeśli toolbar, tabela i panel podglądu potrzebują tego samego modelu i prop drilling robi się głośny, przenieś model listy do szkieletu strony i dziel go przez provide/inject. Jeśli chcesz, by lista była „sticky” między trasami, Pinia to lepszy wybór.

Praktyczna zasada: zaczynaj lokalnie, przejdź do provide/inject, gdy kilka komponentów potrzebuje tego samego modelu, a do Pinia sięgnij tylko wtedy, gdy naprawdę potrzebujesz trwałości między trasami.

Przykład 2: wersje robocze i niezapisane edycje (formularze, którym można zaufać)

Testuj wersje robocze i niezapisane zmiany
Zbuduj formularz edycji z regułami odzyskiwania wersji roboczej, a potem rozszerz do kart i managerów.
Rozpocznij

Wyobraź sobie agenta wsparcia edytującego rekord klienta: dane kontaktowe, rozliczenia i notatki wewnętrzne. Zostaje przerwany, przełącza się ekrany, potem wraca. Jeśli formularz zapomni jego pracę lub zapisze półgotowe dane, zaufanie znika.

Dla wersji roboczych rozdziel trzy rzeczy: ostatnio zapisany rekord, wystawione przez użytkownika zmiany (staged edits) i stan tylko UI jak błędy walidacji.

Lokalny stan: wersje robocze ze zrozumiałymi regułami dirty

Jeśli ekran edycji jest samodzielny, lokalny stan komponentu jest często najbezpieczniejszy. Trzymaj kopię draft rekordu, śledź isDirty (albo mapę dirty na poziomie pól) i przechowuj błędy obok kontrolek formularza.

Prosty flow: załaduj rekord, sklonuj do draftu, edytuj draft i wysyłaj zapytanie zapisu tylko po kliknięciu Save. Cancel odrzuca draft i ponownie ładuje zapisany rekord.

provide/inject: jedna wersja robocza współdzielona między zakładkami

Formularze admina często dzielą się na zakładki lub panele (Profil, Adresy, Uprawnienia). Dzięki provide/inject możesz trzymać jeden model draft i eksponować małe API jak updateField(), resetDraft() i validateSection(). Każda sekcja czyta i zapisuje ten sam draft bez przekazywania propsów przez pięć warstw.

Kiedy Pinia pomaga z wersjami roboczymi

Pinia staje się użyteczna, gdy wersje robocze muszą przetrwać nawigację lub być widoczne poza stroną edycji. Częsty wzorzec to draftsById[customerId], dzięki czemu każdy rekord ma własny draft. To też pomaga, gdy użytkownicy mogą otwierać wiele ekranów edycji jednocześnie.

Błędy z draftami zwykle wynikają z kilku przewidywalnych pomyłek: tworzenie draftu zanim rekord się załaduje, nadpisywanie brudnego draftu przy refetchu, zapominanie o czyszczeniu błędów przy anulowaniu lub używanie jednego wspólnego klucza, który powoduje nadpisanie draftów. Jeśli ustalisz jasne reguły (kiedy tworzyć, nadpisywać, odrzucać, przetrzymywać i zastępować po zapisie), większość tych problemów znika.

Jeśli budujesz panele admina z AppMaster, podział „draft vs zapisany rekord” wciąż obowiązuje: trzymaj draft po stronie klienta i traktuj backend jako źródło prawdy dopiero po udanym Save.

Przykład 3: edycja w wielu kartach bez kolizji stanu

Edycja w wielu kartach to miejsce, gdzie panele admina często się psują. Użytkownik otwiera Klienta A, potem Klienta B, przełącza się i oczekuje, że każda karta zapamięta własne niezapisane zmiany.

Naprawa polega na modelowaniu każdej karty jako własnego pakietu stanu, a nie jednego współdzielonego draftu. Każda karta potrzebuje przynajmniej unikalnego klucza (zwykle na bazie ID rekordu), danych draftu, statusu (clean, dirty, saving) i błędów pól.

Jeśli karty żyją w jednym ekranie, podejście lokalne działa dobrze. Trzymaj listę kart i drafty w komponencie strony renderującym karty. Każdy panel edytora czyta i zapisuje tylko swój pakiet. Gdy karta się zamyka, usuń ten pakiet i po sprawie. To izoluje stan i ułatwia rozumienie zachowania.

Niezależnie od miejsca przechowywania, kształt danych jest podobny:

  • Lista obiektów kart (każdy z customerId, draft, status i errors)
  • activeTabKey
  • Akcje: openTab(id), updateDraft(key, patch), saveTab(key) i closeTab(key)

Pinia staje się lepszym wyborem, gdy karty muszą przetrwać nawigację (przejdź do Orders i wróć) lub gdy wiele ekranów musi otwierać i fokusować karty. Wtedy mały store „tab manager” utrzymuje spójne zachowanie w całej aplikacji.

Główna kolizja do uniknięcia to jeden globalny currentDraft. Działa do momentu, gdy otworzysz drugą kartę — wtedy edycje zaczynają się nadpisywać, błędy walidacji pojawiają się w złym miejscu, a Save aktualizuje zły rekord. Gdy każda otwarta karta ma własny pakiet, kolizje znikają z definicji.

Typowe błędy, które prowadzą do bugów i brudnego kodu

Buduj panel admina szybciej
Wygeneruj aplikację administracyjną Vue3 i backend w Go, a potem zdecyduj, gdzie trzymać stan.
Wypróbuj AppMaster

Większość błędów w panelach admina to nie „bugi Vue”. To błędy projektowe stanu: dane żyją w złym miejscu, dwie części ekranu się nie zgadzają albo stary stan cicho zostaje.

Oto wzorce, które pojawiają się najczęściej:

Wkładanie wszystkiego do Pinia z automatu rozmywa właścicielstwo. Globalny store na początku wydaje się uporządkowany, ale szybko każda strona czyta i zapisuje te same obiekty, a sprzątanie staje się zgadywanką.

Używanie provide/inject bez jasnego kontraktu tworzy ukryte zależności. Jeśli dziecko injectuje filters, ale nie ma umowy kto je providuje i jakie akcje mogą je zmieniać, dostaniesz niespodziewane aktualizacje, gdy inne dziecko zacznie mutować ten sam obiekt.

Mieszanie server state i UI state w tym samym store powoduje przypadkowe nadpisania. Pobierane rekordy zachowują się inaczej niż „czy drawer jest otwarty?”, „aktualna karta” czy „brudne pola”. Gdy żyją razem, refetch może zadeptać UI albo zmiany UI mogą mutować cache.

Pomijanie czyszczenia lifecycle pozwala stanowi przeciekać. Filtry z jednej widoku mogą wpływać na inny, a wersje robocze pozostawać po opuszczeniu strony. Następnym razem ktoś otworzy inny rekord i zobaczy stare zaznaczenia, myśląc, że aplikacja jest uszkodzona.

Złe kluczowanie draftów to cichy zabójca zaufania. Jeśli trzymasz drafty pod jednym kluczem jak draft:editUser, edytowanie Użytkownika A a potem B nadpisze ten sam draft.

Prosta reguła zapobiega większości problemów: trzymaj stan jak najbliżej miejsca jego użycia i podnoś go tylko wtedy, gdy dwie niezależne części naprawdę muszą się dzielić. Gdy się dzielisz, zdefiniuj właściciela (kto może zmieniać) i tożsamość (jak jest kluczowany).

Szybka lista kontrolna przed wyborem: lokalny, provide/inject czy Pinia

Przenieś workflowy admina na mobile
Generuj natywne aplikacje iOS i Android, gdy workflowy admina potrzebują dostępu z telefonu.
Zbuduj aplikację mobilną

Najbardziej użyteczne pytanie brzmi: kto jest właścicielem tego stanu? Jeśli nie potrafisz odpowiedzieć jednym zdaniem, stan prawdopodobnie robi za dużo i powinien zostać podzielony.

Użyj tych checków jako szybkiego filtra:

  • Czy potrafisz wskazać właściciela (komponent, strona, cała aplikacja)?
  • Czy musi przetrwać zmianę trasy lub reload? Jeśli tak, zaplanuj persystencję zamiast polegać na przeglądarce.
  • Czy będzie edytowanych kilka rekordów jednocześnie? Jeśli tak, kluczuj stan po ID rekordu.
  • Czy stan używają tylko komponenty pod jednym page shell? Jeśli tak, provide/inject często pasuje.
  • Czy potrzebujesz inspekcji zmian i rozumienia, kto co zmienił? Jeśli tak, Pinia jest często najczytelniejszym miejscem dla tego kawałka.

Dopasowanie narzędzi, prosto:

Jeśli stan żyje i umiera w jednym komponencie (np. flaga otwarte/zamknięte dropdown), trzymaj go lokalnie. Jeśli kilka komponentów na tym samym ekranie potrzebuje współdzielonego kontekstu (filter bar + tabela + podsumowanie), provide/inject umożliwia współdzielenie bez globalizacji. Jeśli stan musi być współdzielony między ekranami, przetrwać nawigację lub wymaga przewidywalnych, debugowalnych aktualizacji, sięgnij po Pinia i kluczowanie wpisów po ID rekordu, gdy chodzi o drafty.

Jeśli budujesz UI admina w Vue 3 (w tym wygenerowanym narzędziami jak AppMaster), ta lista kontrolna pomoże uniknąć wczesnego wkładania wszystkiego do store.

Następne kroki: rozwijanie stanu bez robienia bałaganu

Najbezpieczniejszy sposób na ulepszanie zarządzania stanem w panelach admina to rosnąć w małych, nudnych krokach. Zacznij od lokalnego stanu dla wszystkiego, co zostaje na jednej stronie. Gdy zobaczysz prawdziwe ponowne użycie (skopiowana logika, trzeci komponent potrzebuje stanu), przenieś go o poziom wyżej. Dopiero wtedy rozważ wspólny store.

Ścieżka, która działa dla większości zespołów:

  • Trzymaj stan ograniczony do strony lokalnie najpierw (filtry, sort, paginacja, otwarte/zamknięte panele).
  • Użyj provide/inject, gdy kilka komponentów na tej samej stronie potrzebuje współdzielonego kontekstu.
  • Dodawaj po jednym store Pinia na raz dla potrzeb międzyekranowych (draft manager, tab manager, current workspace).
  • Zapisuj reguły resetu i się ich trzymaj (co resetuje się przy nawigacji, logout, Clear filters, Discard changes).

Reguły resetu wydają się drobne, ale zapobiegają większości „dlaczego to się zmieniło?” momentów. Zdecyduj np., co dzieje się z draftem, gdy ktoś otworzy inny rekord i potem wróci: przywrócić, ostrzec czy zresetować. Potem trzymaj to zachowanie konsekwentnie.

Jeśli wprowadzisz store, trzymaj go „kształtowanym funkcjonalnie”. Store z draftami powinien obsługiwać tworzenie, przywracanie i czyszczenie draftów, ale nie powinien też trzymać filtrów tabeli ani ustawień layoutu UI.

Jeśli chcesz szybko prototypować panel admina, AppMaster (appmaster.io) może wygenerować aplikację Vue3 wraz z backendem i logiką biznesową, a potem nadal możesz dopracowywać wygenerowany kod tam, gdzie potrzebujesz niestandardowego zarządzania stanem. Praktyczny następny krok to zbudować jeden ekran end-to-end (np. formularz edycji z odzyskiwaniem draftu) i zobaczyć, co naprawdę potrzebuje Pinia, a co może pozostać lokalne.

FAQ

When should I keep state local in a Vue 3 admin panel?

Użyj lokalnego stanu, gdy dane dotyczą tylko jednego komponentu i mogą zostać zresetowane, gdy komponent zostanie odmontowany. Typowe przykłady to otwieranie/zamykanie dialogu, wybrane wiersze w jednej tabeli oraz sekcja formularza, która nie jest używana w innych miejscach.

When is `provide/inject` better than a store?

Użyj provide/inject, gdy kilka komponentów na tej samej stronie potrzebuje jednej źródła prawdy, a przekazywanie propsów robi się uciążliwe. Dostarczaj tylko to, co rzeczywiście potrzebne, żeby strona pozostała czytelna.

What’s the clearest sign I should use Pinia?

Sięgnij po Pinia, gdy stan musi być współdzielony między trasami, przetrwać nawigację lub być łatwy do zdebugowania w jednym miejscu. Typowe przykłady to aktualne workspace, uprawnienia, feature flagi oraz menedżery międzyekranowe jak drafts czy tabs.

How do I classify state before choosing a tool?

Zacznij od nazwania typu stanu (UI, server, form, cross-screen), potem zdefiniuj zakres (jeden komponent, jedna strona, wiele tras), czas życia (reset przy unmount, przetrwać nawigację, przetrwać reload) i konkurencję (pojedynczy edytor czy wiele kart). Od tych czterech etykiet zwykle wynika wybór narzędzia.

Should table filters live in the URL, local state, or Pinia?

Jeśli użytkownicy mają dzielić widok lub spodziewają się jego odtworzenia, umieść filtry i paginację w query params, żeby przetrwały reload i dało się je skopiować. Jeśli chodzi o „wróć do listy tak jak ją zostawiłem” między trasami — Pinia. W przeciwnym razie trzymaj je w stanie strony.

What’s the safest way to handle unsaved edits in big admin forms?

Oddziel ostatnio zapisany rekord od wersji roboczej użytkownika i zapisuj na serwer tylko po kliknięciu Save. Śledź jasne reguły dirty i zadecyduj, co zrobić przy nawigacji (ostrzeżenie, auto-save albo odzyskiwalna wersja robocza), żeby użytkownicy nie tracili pracy.

How do I avoid multi-tab editing collisions?

Daj każdemu otwartemu edytorowi własny pakiet stanu, kluczowany ID rekordu (czasem plus klucz karty), zamiast jednego globalnego currentDraft. To zapobiega nadpisywaniu i mieszaniu błędów walidacji między kartami.

Should drafts be local, provided, or stored in Pinia?

Strona-owned provide/inject działa, gdy cały flow edycji mieści się na jednej trasie. Jeśli wersje robocze muszą przetrwać zmianę trasy lub być dostępne poza ekranem edycji, Pinia z strukturą taką jak draftsById[recordId] jest zwykle prostsze i bardziej przewidywalne.

What state should be computed instead of stored?

Nie przechowuj tego, co można wyliczyć. Badges, podsumowania i flagi „can save” lepiej robić jako computed, żeby nie zaciągały się i nie rozjeżdżały ze źródłem prawdy.

What are the most common state mistakes in admin panels?

Domyślne wkładanie wszystkiego do Pinia, mieszanie danych z serwera z przełącznikami UI oraz brak czyszczenia stanu przy nawigacji to najczęstsze źródła dziwnego zachowania. Uważaj też na złe klucze, np. jeden wspólny draft key, który nadpisuje różne rekordy.

Łatwy do uruchomienia
Stworzyć coś niesamowitego

Eksperymentuj z AppMaster z darmowym planem.
Kiedy będziesz gotowy, możesz wybrać odpowiednią subskrypcję.

Rozpocznij