Wybrałeś Vue dla jego łagodnej krzywej uczenia, a teraz musisz dostarczyć złożone SPA z TypeScript, Pinia stores i composables, które twój zespół faktycznie może utrzymać. Te przepisy dają ci gotowe do produkcji prompty generujące idiomatyczny kod Vue 3 — nie pozostałości Options API przebrane za Composition API.
Prompty do generowania komponentów Vue 3 z <script setup> i TypeScript
Wzorce store Pinia z właściwym typowaniem i persystencją
Przepisy composable dla ekstrahowania logiki wielokrotnego użytku
Prompty testowe dla Vue Test Utils i Vitest
Scenariusz: Potrzebujesz nowego komponentu funkcji zgodnego z konwencjami twojego zespołu — <script setup>, typowane propsy z domyślnymi, typowane emity i scoped style.
Wskazówka
Utwórz komponent Vue 3 w src/components/UserCard.vue używając <script setup lang="ts">. Zdefiniuj propsy z defineProps<{ user: User; showActions?: boolean; compact?: boolean }>() używając withDefaults do ustawienia showActions na true i compact na false. Zdefiniuj emity z defineEmits<{ edit: [userId: string]; delete: [userId: string]; select: [user: User] }>(). Dołącz import interfejsu User z @/types. Użyj Tailwind CSS w szablonie pokazującym avatar użytkownika, nazwę, email i badge roli. Gdy showActions to true, pokaż przyciski ikon edycji i usuwania. Gdy compact to true, ukryj email i rolę. Dodaj blok <style scoped> tylko dla animacji. Napisz towarzyszący test jednostkowy używający Vue Test Utils i Vitest montujący komponent z mockowymi danymi i weryfikujący każde zachowanie propsa i emit.
Oczekiwany wynik: Plik .vue SFC z typowanym <script setup>, responsywnym szablonem i plikiem .test.ts.
Scenariusz: Potrzebujesz store koszyka persystującego między odświeżeniami strony, wspierającego cofnij i integrującego się z Vue DevTools.
Wskazówka
Utwórz store Pinia w src/stores/cart.ts używając składni setup (styl composable) dla lepszego wnioskowania TypeScript. Stan: tablica items (CartItem[]), couponCode string lub null, isCheckingOut boolean. Gettery: totalItems (suma ilości), subtotal (suma ceny razy ilość), discount (obliczone z kuponu), total (subtotal minus rabat). Akcje: addItem (inkrementuj ilość jeśli istnieje, w przeciwnym razie wypchnij), removeItem, updateQuantity (z walidacją min 1), applyCoupon (waliduj względem endpointu API), clearCart, checkout (async, ustawia isCheckingOut, wywołuje API, czyści koszyk przy sukcesie). Użyj pinia-plugin-persistedstate do synchronizacji z localStorage. Zaimplementuj cofnij dla ostatniej modyfikacji koszyka używając stosu historii. Eksportuj typowany composable. Napisz testy dla każdej akcji włącznie z zachowaniem cofnij.
Oczekiwany wynik: Plik store, definicja typu CartItem i plik testowy pokrywający wszystkie akcje i cofnij.
Scenariusz: Wiele komponentów duplikuje ten sam wzorzec fetch-with-loading-state, debounced search i sprawdzanie uprawnień. Wyekstrahuj je do composables.
Wskazówka
Utwórz te composables w src/composables/, każde we własnym pliku z pełnymi generikami TypeScript:
useFetch<T>(url: MaybeRef<string>, options?) — reaktywne obserwowanie URL, auto-refetch przy zmianie URL, zwraca { data: Ref<T | null>, error: Ref<Error | null>, isLoading: Ref<boolean>, execute, abort }. Obsługuje czyszczenie AbortController przy unmount komponentu.
useSearch<T>(searchFn: (query: string) => Promise<T[]>, delay?: number) — debounced search z domyślnym opóźnieniem 300ms, zwraca { query, results, isSearching }. Anuluje oczekujące wyszukiwania przy zmianie zapytania.
usePermission(permission: string) — sprawdza względem store auth, zwraca { hasPermission: ComputedRef<boolean>, isLoading }. Cache’uje wyniki per string uprawnienia.
usePagination<T>(fetchFn: (page, pageSize) => Promise<PaginatedResponse<T>>) — zwraca { items, currentPage, totalPages, pageSize, isLoading, goToPage, nextPage, prevPage }.
Eksportuj wszystkie z src/composables/index.ts. Napisz testy dla każdego używając mount Vue Test Utils z komponentem testowym konsumującym composable.
Oczekiwany wynik: Cztery pliki composable, cztery pliki testowe, definicje typów i barrel export.
Scenariusz: Potrzebujesz formularza checkout z 4 etapami, gdzie każdy etap waliduje przed przejściem, a użytkownik może nawigować wstecz bez utraty danych.
Wskazówka
Zbuduj system formularzy wieloetapowych w src/components/checkout/. Utwórz: (1) MultiStepForm.vue — zarządza bieżącym indeksem kroku, waliduje bieżący krok przed przejściem, eksponuje nawigację przez provide/inject, aby kroki potomne mogły wywołać next/prev/goTo. (2) FormStep.vue — generyczny wrapper kroku przyjmujący schemat Zod i walidujący swoje pola przy “Next”. (3) Indywidualne komponenty kroków: ShippingStep.vue, BillingStep.vue, PaymentStep.vue, ReviewStep.vue. (4) Użyj VeeValidate z adapterem Zod dla walidacji per-etap. (5) Wskaźnik postępu pokazujący ukończone, bieżące i nadchodzące kroki. (6) Composable useCheckoutForm() agregujący wszystkie dane kroków do jednego typowanego obiektu i submitujący do API. Persystuj częściowo ukończone dane formularza do sessionStorage, aby użytkownik nie stracił postępu przy przypadkowym odświeżeniu strony. Testuj nawigację kroków, blokowanie walidacji i persystencję danych.
Oczekiwany wynik: Sześć plików komponentów, jeden composable, schematy Zod dla każdego kroku i testy integracyjne.
Scenariusz: Twój panel administracyjny musi wyświetlać 50 000 wpisów dziennika bez zamrażania przeglądarki.
Wskazówka
Utwórz komponent VirtualDataTable.vue obsługujący duże zbiory danych używając vue-virtual-scroller. Funkcje: (1) Generyczne typowane kolumny przez props columns z typem ColumnDef<T>. (2) Sortowalne nagłówki — kliknij, aby przełączać przez asc/desc/none. (3) Filtry kolumn renderowane pod każdym nagłówkiem. (4) Stały nagłówek pozostający widoczny podczas przewijania. (5) Wybór wiersza z Shift+klik dla wyboru zakresu. (6) Zmienne rozmiary kolumn z uchwytami przeciągania. (7) Eksport wybranych wierszy do CSV. Komponent powinien akceptować props data (reaktywna tablica) i props loading. Podczas ładowania, pokaż wiersze szkieletowe. Wewnętrznie, obliczaj przefiltrowane i posortowane dane jako właściwości computed, aby aktualizowały się reaktywnie. Utrzymuj wirtualny scroller renderujący tylko widoczne wiersze. Testuj z zestawem danych 50 000 wierszy, aby zweryfikować brak porzuconych klatek.
Oczekiwany wynik: Komponent VirtualDataTable, definicje typów kolumn, narzędzie eksportu CSV i test wydajności.
Scenariusz: Potrzebujesz systemu motywów pozwalającego każdemu komponentowi uzyskać dostęp i przełączać między motywami light, dark i system bez prop drilling.
Wskazówka
Utwórz system motywów używając provide/inject Vue z bezpieczeństwem TypeScript. (1) Zdefiniuj interfejs ThemeContext z theme (light/dark/system), resolvedTheme (light/dark, obliczone z preferencji systemu gdy theme to ‘system’), toggleTheme(), setTheme(theme). (2) Utwórz ThemeProvider.vue dostarczający kontekst, czytający początkowy motyw z localStorage, obserwujący preferencje systemu przez matchMedia('(prefers-color-scheme: dark)'), stosujący klasę dark do document.documentElement. (3) Utwórz composable useTheme() wstrzykujący kontekst z błędem runtime jeśli używany poza providerem. (4) Utwórz komponent ThemeToggle.vue z trzema stanami (ikona słońca, ikona księżyca, ikona monitora). (5) Zapewnij kompatybilność SSR — nie dostęp do window lub document podczas renderowania serwera. Użyj onMounted dla kodu tylko przeglądarki. Testuj przełączanie motywu, wykrywanie preferencji systemu i persystencję.
Oczekiwany wynik: Komponent providera, composable, komponent toggle, definicje typów i testy.
Scenariusz: Twoja konfiguracja Vue Router ładuje wszystkie komponenty stron gorliwie, nadymając początkowy pakiet.
Wskazówka
Zrefaktoryzuj src/router/index.ts, aby używać leniwie ładowanych tras. Dla każdej trasy: (1) Zamień statyczne importy na () => import('../views/PageName.vue'). (2) Dodaj właściwość meta.skeleton per trasa referującą lekki komponent szkieletowy pasujący do layoutu tej strony. (3) Utwórz komponent RouterViewWithSuspense.vue owijający <RouterView> w <Suspense>, renderujący szkielet trasy jako fallback i przechwytujący błędy chunk-load z UI retry. (4) Dodaj prefetching tras: utwórz composable usePrefetch() preładujący chunki tras przy mouseenter linków nawigacyjnych po opóźnieniu hover 150ms. (5) Grupuj powiązane trasy w nazwane chunki. Weryfikuj, że każda trasa ładuje się jako oddzielny chunk w produkcyjnym buildzie.
Oczekiwany wynik: Zaktualizowana konfiguracja routera, komponent RouterViewWithSuspense, composable usePrefetch i komponenty szkieletowe.
Scenariusz: Twoja aplikacja potrzebuje globalnego systemu powiadomień toast, który każdy komponent może wywołać bez prop drilling.
Wskazówka
Utwórz system powiadomień toast w src/components/toast/. (1) ToastProvider.vue — renderuje stały kontener w prawym dolnym rogu, zarządza reaktywną kolejką obiektów toast, dostarcza kontekst useToast(). (2) Toast.vue — indywidualny toast z ikoną (success/error/warning/info), tytułem, wiadomością, opcjonalnym przyciskiem akcji, auto-dismiss timer (domyślnie 5 sekund, konfigurowalne), dismiss przy kliknięciu i przejścia slide-in/slide-out używające <Transition>. (3) Composable useToast() — zwraca { success(msg, options?), error(msg, options?), warning(msg, options?), info(msg, options?), dismiss(id), clearAll() }. Opcje zawierają duration, action label, action callback i persistent (bez auto-dismiss). (4) Układaj toasty pionowo z maksymalnie 5 widocznych. Gdy przekracza 5, zwiń starsze toasty w wskaźnik “+N więcej”. Testuj tworzenie toastu, timing auto-dismiss, manualne dismiss i callback akcji.
Oczekiwany wynik: ToastProvider, komponent Toast, composable useToast i testy.
Scenariusz: Twoje SPA musi wspierać angielski, hiszpański i japoński z leniwie ładowanymi plikami locale i pluralizacją.
Wskazówka
Skonfiguruj Vue I18n v9 z leniwie ładowanymi locale. (1) Utwórz src/i18n/index.ts inicjalizujący vue-i18n z en jako domyślnym, legacy mode wyłączony. (2) Utwórz pliki locale w src/i18n/locales/en.json, es.json, ja.json z przynajmniej 30 kluczami pokrywającymi typowe wzorce UI: nawigacja, formularze, powiadomienia, daty i przykłady pluralizacji. (3) Zaimplementuj leniwe ładowanie: utwórz loadLocale(locale) dynamicznie importujący plik JSON i wywołujący i18n.global.setLocaleMessage(). (4) Utwórz komponent LocaleSwitcher.vue pokazujący dropdown przełączający locale przy wyborze, persystując do localStorage. (5) Utwórz composable useI18nRoute() prefiksujący wszystkie trasy z bieżącym locale i przekierowujący przy zmianie locale. (6) Obsługuj formatowanie dat i liczb używając $d() i $n() vue-i18n. Testuj, że przełączanie locale aktualizuje cały widoczny tekst bez przeładowania strony.
Oczekiwany wynik: Konfiguracja I18n, trzy pliki locale, przełącznik locale, composable routingu i testy integracyjne.
Scenariusz: Twoja aplikacja czuje się statyczna. Potrzebujesz komponentów przejść wielokrotnego użytku dla zmian stron, animacji list i mikro-interakcji.
Wskazówka
Utwórz bibliotekę animacji w src/components/transitions/. (1) FadeTransition.vue — owija <Transition> z CSS fade in/out, konfigurowalne props duration. (2) SlideTransition.vue — slide z lewej, prawej, góry lub dołu przez props direction. (3) ScaleTransition.vue — scale z 0.95 do 1 z opacity. (4) ListTransition.vue — owija <TransitionGroup> dla rozłożonych w czasie animacji list, gdzie każdy element wchodzi 50ms po poprzednim. (5) PageTransition.vue — dla przejść tras, wykrywa kierunek nawigacji (forward/back) i slide odpowiednio. (6) CollapseTransition.vue — animuje wysokość z 0 do auto dla sekcji accordion/rozszerzalnych. Każdy komponent powinien używać CSS transitions dla wydajności, akceptować propsy duration i easing oraz działać z v-if i v-show. Utwórz stronę demo pokazującą wszystkie przejścia.
Oczekiwany wynik: Sześć komponentów przejść, strona demo i definicje typów dla wszystkich propsów.
Scenariusz: Twój pulpit potrzebuje aktualizacji real-time z WebSocket obsługującego rozłączenia gracefully.
Wskazówka
Utwórz composable useWebSocket(url, options?) w src/composables/useWebSocket.ts. Funkcje: (1) Reaktywny stan połączenia: ref status jako ‘connecting’ | ‘open’ | ‘closed’ | ‘error’. (2) Auto-reconnect z wykładniczym backoffem (1s, 2s, 4s, 8s, max 30s), konfigurowalne max retries. (3) Heartbeat ping/pong co 30 sekund do wykrywania martwych połączeń. (4) Kolejkowanie wiadomości: wiadomości wysłane podczas rozłączenia są kolejkowane i spłukiwane przy reconnect. (5) Typowana obsługa wiadomości: akceptuj generyczny onMessage<T>(type, handler) filtrujący wiadomości po polu type. (6) Uwierzytelnianie: wyślij token auth przy connect i reconnect. (7) Czyszczenie przy unmount komponentu. (8) Metoda send(type, data) JSON-serializująca i wysyłająca. Utwórz composable useRealtimeTodos() owijający useWebSocket dla aktualizacji todo, synchronizując z store Pinia. Testuj zachowanie reconnection i kolejkowanie wiadomości.
Oczekiwany wynik: Composable useWebSocket, composable useRealtimeTodos i testy dla logiki reconnection.
Scenariusz: Twojej bibliotece komponentów brakuje dokumentacji. Nowi członkowie zespołu nie mogą odkryć ani zrozumieć istniejących komponentów.
Wskazówka
Skonfiguruj Storybook 8 dla tego projektu Vue 3 z builderem Vite. (1) Zainstaluj i skonfiguruj @storybook/vue3-vite z autodocs. (2) Utwórz stories dla 5 istniejących komponentów: Button, Input, Modal, Card i DataTable. Każdy plik story powinien zawierać: domyślny export z argTypes pasującymi do propsów komponentu, story Primary pokazującą domyślne użycie, story gallery pokazującą wszystkie warianty w siatce, interaktywną story gdzie każdy props jest sterowalny przez kontrolki Storybook i stronę dokumentacji używającą MDX. (3) Skonfiguruj Storybook, aby rozwiązywać te same aliasy ścieżek co główna konfiguracja Vite. (4) Dodaj @storybook/addon-a11y i pokazuj wyniki audytu dostępności dla każdej story. (5) Dodaj @storybook/test dla testowania interakcji w stories. Napisz test interakcji dla story Modal klikający otwórz, weryfikujący pułapkę fokusa i zamykający z Escape.
Oczekiwany wynik: Konfiguracja Storybook, 5 plików story z wariantami i docs, addon dostępności i jeden test interakcji.