Niestandardowe komponenty Vue w generowanym interfejsie — bezpiecznie przy ponownym generowaniu
Dowiedz się, jak dodawać niestandardowe komponenty Vue do generowanego UI bez utraty pracy przy regeneracji, stosując izolację, wyraźne granice i proste zasady przekazywania.

Co psuje się, gdy edytujesz generowany interfejs
Generowane interfejsy są przeznaczone do ponownego tworzenia. W platformach takich jak AppMaster kod aplikacji Vue3 powstaje z wizualnych kreatorów. Regeneracja to sposób, w jaki zmiany pozostają spójne między ekranami, logiką i modelami danych.
Problem jest prosty: jeśli bezpośrednio edytujesz pliki wygenerowane, następna regeneracja może nadpisać twoje zmiany.
Dlatego zespoły sięgają po kod niestandardowy. Wbudowane bloki UI często pokrywają standardowe formularze i tabele, ale prawdziwe aplikacje zwykle potrzebują kilku specjalnych elementów: zaawansowane wykresy, wybieraki na mapie, edytory tekstu sformatowanego, panele podpisu czy plany z przeciągnij‑upuść. To dobre powody, żeby dodać niestandardowe komponenty Vue — pod warunkiem, że traktujesz je jak dodatki, a nie bezpośrednie modyfikacje.
Gdy kod niestandardowy miesza się z generowanym, błędy mogą pojawiać się późno i być mylące. Możesz ich nie zauważyć aż do następnej zmiany UI, która wymusi regenerację, albo gdy ktoś z zespołu edytuje ekran w edytorze wizualnym. Typowe problemy to:
- Twój niestandardowy markup znika, bo szablon został wygenerowany na nowo.
- Importy lub rejestracja przestają działać, bo nazwy plików lub struktura się zmieniła.
- „Mała poprawka" staje się konfliktem scalania przy każdym wdrożeniu.
- Logika generowana i niestandardowa odpływają od siebie i zaczynają zawodzić w skrajnych przypadkach.
- Aktualizacje wydają się ryzykowne, bo nie wiesz, co zostanie zastąpione.
Celem nie jest unikanie dostosowań. Chodzi o to, by przebudowy były przewidywalne. Jeśli utrzymasz czystą granicę między wygenerowanymi ekranami a niestandardowymi widżetami, regeneracja pozostanie rutyną zamiast być stresującym zadaniem.
Zasada granicy, która chroni przed problemami przy regeneracji
Jeśli chcesz dostosowywać bez utraty pracy, wprowadź jedną zasadę: nigdy nie edytuj wygenerowanych plików. Traktuj je jako wyjście tylko do odczytu, jak skompilowany artefakt.
Pomyśl o UI jako o dwóch strefach:
- Strefa generowana: strony, układy i ekrany tworzone przez generator.
- Strefa niestandardowa: twoje ręcznie pisane komponenty Vue w oddzielnym katalogu.
Generowane UI powinno konsumować twoje komponenty niestandardowe. Nie powinno być miejscem, w którym te komponenty są budowane.
Aby to działało długoterminowo, utrzymaj „granice" małe i jasne. Widżet niestandardowy powinien zachowywać się jak mały produkt z kontraktem:
- Propsy wchodzą: tylko to, co potrzebne do renderowania.
- Eventy wychodzą: tylko to, na co strona musi reagować.
Unikaj zaglądania do globalnego stanu lub wywoływania niepowiązanych API wewnątrz widżetu, chyba że to wyraźna część kontraktu.
W przypadku generowanych ekranów Vue3 w stylu AppMaster oznacza to zazwyczaj minimalne okablowanie w wygenerowanym ekranie, by przekazać propsy i obsłużyć eventy. To okablowanie może się zmieniać przy regeneracji, ale pozostaje małe i łatwe do odtworzenia. Prawdziwa praca pozostaje bezpieczna w strefie niestandardowej.
Wzorce izolacji dobrze współgrające z Vue3
Cel jest prosty: regeneracja powinna swobodnie zastępować generowane pliki, a twój kod widżetu ma pozostać nienaruszony.
Praktyczne podejście to trzymanie wyspecjalizowanych widżetów jako małego, wewnętrznego modułu: komponenty, style i pomocnicze narzędzia w jednym miejscu. W generowanych aplikacjach Vue3 zwykle oznacza to, że kod niestandardowy żyje poza generowanymi stronami i jest importowany jako zależność.
Komponent‑wrapper bardzo pomaga. Niech wrapper rozmawia z wygenerowaną aplikacją: odczytuje istniejący kształt danych strony, normalizuje go i przekazuje czyste propsy do widżetu. Jeśli kształt danych generowanych zmieni się później, często wystarczy zaktualizować wrapper zamiast przepisywać widżet.
Kilka wzorców, które dobrze się sprawdzają:
- Traktuj widżet jako czarną skrzynkę: propsy wchodzą, eventy wychodzą.
- Użyj wrappera do mapowania odpowiedzi API, dat i identyfikatorów na formaty przyjazne widżetowi.
- Trzymaj style scoped, żeby wygenerowane strony nie nadpisywały przypadkowo twojego widżetu.
- Nie polegaj na strukturze DOM rodzica ani na specyficznych klasach stron.
Jeśli chodzi o stylowanie, preferuj scoped CSS (lub CSS Modules) i nazwij klasy z namespace. Jeśli widżet musi pasować do motywu aplikacji, przekaż tokeny motywu jako propsy (kolory, odstępy, rozmiary fontów) zamiast importować style strony.
Sloty są bezpieczne, gdy są małe i opcjonalne, np. komunikat dla stanu pustego. Jeśli sloty zaczynają kontrolować kluczowy układ lub zachowanie, znów przenosisz widżet do warstwy generowanej, a to właśnie powoduje problemy przy regeneracji.
Projektowanie stabilnego kontraktu komponentu (propsy i eventy)
Najbezpieczniejszy sposób, by utrzymać regenerację bezbolesną, to traktować każdy widżet jak stabilny interfejs. Ekrany generowane mogą się zmieniać. Twój komponent nie powinien.
Zacznij od wejść (propsów). Trzymaj je niewielkie, przewidywalne i łatwe do walidacji. Wybieraj proste prymitywy i zwykłe obiekty, które kontrolujesz. Dodaj wartości domyślne, żeby widżet zachowywał się sensownie, nawet gdy strona jeszcze nic nie przekaże. Jeśli coś może być nieprawidłowe (ID, ciągi dat, wartości przypominające enum), waliduj to i zakończ łagodnie: pokaż stan pusty zamiast awarii.
Dla wyjść, ustandaryzuj eventy, by widżety były spójne z resztą aplikacji. Zestaw minimalny to:
update:modelValuedlav-modelchangedla potwierdzonych zmian (nie każdego keystroke’a)errorgdy komponent nie może wykonać zadaniareadygdy praca asynchroniczna się zakończy i widżet jest używalny
Jeśli w grę wchodzi praca asynchroniczna, włącz ją do kontraktu. Udostępnij propsy loading i disabled oraz rozważ errorMessage dla błędów po stronie serwera. Jeśli komponent sam pobiera dane, nadal emituj error i ready, żeby rodzic mógł zareagować (toast, logowanie, UI zapasowy).
Oczekiwania dotyczące dostępności
Wbuduj dostępność w kontrakt. Przyjmuj label (lub ariaLabel), udokumentuj zachowanie klawiatury i zachowaj przewidywalne ustawienie fokusu po akcjach.
Na przykład widżet timeline na dashboardzie powinien wspierać klawisze strzałek do poruszania się między elementami, Enter do otwierania szczegółów i powinien zwracać fokus do kontrolki, która otworzyła dialog, gdy dialog się zamknie. To sprawia, że widżet jest wielokrotnego użytku na regenerowanych ekranach bez dodatkowych przeróbek.
Krok po kroku: dodaj niestandardowy widżet bez dotykania generowanych plików
Zacznij od małego kroku: jednego ekranu, na którym zależy użytkownikom, i jednego widżetu, który wyróżnia stronę. Wąska zmiana ułatwia obserwowanie, co regeneracja wpływa, a co nie.
-
Utwórz komponent poza obszarem generowanym. Umieść go w katalogu, który kontrolujesz i trzymasz w repozytorium (często
customlubextensions). -
Trzymaj publiczną powierzchnię małą. Kilka propsów w, kilka eventów na zewnątrz. Nie przekazuj całego stanu strony.
-
Dodaj cienki wrapper, którym też zarządzasz. Jego zadaniem jest przetłumaczyć „dane strony generowanej" na kontrakt widżetu.
-
Zintegruj przez obsługiwany punkt rozszerzeń. Odwołuj się do wrappera w sposób, który nie wymaga edycji generowanych plików.
-
Zregeneruj i zweryfikuj. Twój katalog z customem, wrapper i komponent powinny pozostać niezmienione i kompilować się.
Utrzymuj granice ostre. Widżet skupia się na prezentacji i interakcji. Wrapper mapuje dane i przekazuje akcje. Reguły biznesowe leżą w warstwie logiki aplikacji (backend lub procesy współdzielone), a nie ukryte w widżecie.
Przydatny test: gdyby regeneracja odbyła się teraz, czy kolega z zespołu mógłby odbudować aplikację i uzyskać ten sam wynik bez ręcznych poprawek? Jeśli tak, wzorzec jest solidny.
Gdzie umieszczać logikę, by UI było łatwe w utrzymaniu
Widżet niestandardowy powinien zajmować się głównie wyglądem i reakcją na wejście użytkownika. Im więcej reguł biznesowych pakujesz do widżetu, tym trudniej go ponownie użyć, testować i zmieniać.
Dobrym domyślnym podejściem jest: trzymaj logikę biznesową w warstwie strony lub feature, a widżet rób "głupim". Strona decyduje, jakie dane trafiają do widżetu i co się dzieje, gdy widżet emituje event. Widżet renderuje i zgłasza intencję użytkownika.
Gdy logika musi być blisko widżetu (formatowanie, mały stan, walidacja po stronie klienta), ukryj ją za małą warstwą serwisową. W Vue3 może to być moduł, composable lub store z jasnym API. Widżet importuje to API, a nie przypadkowe wewnętrzne elementy aplikacji.
Praktyczny podział:
- Widżet (komponent): stan UI, obsługa wejścia, wygląd, emituje eventy jak
select,change,retry. - Serwis/composable: kształtowanie danych, cache, mapowanie błędów API na komunikaty dla użytkownika.
- Strona/kontener: reguły biznesowe, uprawnienia, które dane ładować, kiedy zapisywać.
- Części generowane aplikacji: pozostawione bez zmian; przekazują dane i nasłuchują eventów.
Unikaj bezpośrednich wywołań API wewnątrz widżetu, chyba że to wyraźny kontrakt widżetu. Jeśli odpowiada za pobieranie, nazwij go odpowiednio (np. CustomerSearchWidget) i trzymaj kod wywołań w jednym serwisie. W przeciwnym razie przekaż items, loading i error jako propsy.
Komunikaty o błędach powinny być przyjazne i spójne. Zamiast wyświetlać surowy tekst serwera, mapuj błędy na zestaw komunikatów używanych w całej aplikacji, np. „Nie udało się załadować danych. Spróbuj ponownie.” Dodaj akcję ponawiania, gdy to możliwe, i loguj szczegóły poza widżetem.
Przykład: niestandardowy widżet ApprovalBadge nie powinien decydować, czy faktura jest do zatwierdzenia. Niech strona wyliczy status i canApprove. Odznaka emituje approve, a strona uruchamia właściwe reguły i wywołuje backend (np. API modelowane w AppMaster), a potem przekazuje stan sukcesu lub błędu z powrotem do UI.
Częste błędy, które powodują ból po regeneracji
Większość problemów nie dotyczy samego Vue. Pochodzą z mieszania pracy niestandardowej w miejscach, które generator posiada, albo z polegania na szczegółach, które mogą się zmieniać.
Błędy, które najczęściej zmieniają mały widżet w konieczność ciągłego sprzątania:
- Edycja generowanych plików Vue i zapomnienie, co zostało zmienione.
- Używanie globalnego CSS lub szerokich selektorów, które cicho wpływają na inne ekrany, gdy markup się zmienia.
- Odczytywanie lub mutowanie kształtu generowanego stanu bezpośrednio, tak że drobna zmiana nazwy łamie widżet.
- Upchanie zbyt wielu założeń specyficznych dla strony do jednego komponentu.
- Zmiana API komponentu (propsów/eventów) bez planu migracji.
Typowy scenariusz: dodajesz niestandardową tabelę i działa. Po miesiącu zmiana układu generowanego powoduje, że globalna reguła .btn zaczyna wpływać na stronę logowania i admina. Albo obiekt danych zmienia user.name na user.profile.name i widżet przestaje działać. Problem nie leży w widżecie — leży w zależności od niestabilnych szczegółów.
Dwa nawyki zapobiegają większości z tego:
Po pierwsze, traktuj kod generowany jako tylko do odczytu i trzymaj pliki custom oddzielnie, z jasną granicą importu.
Po drugie, utrzymuj kontrakt komponentu mały i jawny. Jeśli musisz go rozwijać, dodaj prosty prop wersji (np. apiVersion) lub obsłuż jednocześnie stary i nowy kształt propsów przez jedno wydanie.
Szybka lista kontrolna przed wypuszczeniem niestandardowego komponentu
Zanim scalisz widżet z aplikacją Vue3, zrób szybki test rzeczywistości. Powinien przetrwać kolejną regenerację bez heroicznych działań, a ktoś inny powinien móc go ponownie użyć.
- Test regeneracji: uruchom pełną regenerację i przebuduj. Jeśli musiałeś ponownie edytować wygenerowany plik, granica jest ustawiona źle.
- Jasne wejścia i wyjścia: propsy w, emits out. Unikaj magicznych zależności jak dostęp do zewnętrznego DOM czy założenie konkretnego store’a strony.
- Zawieranie stylów: scope’uj style i użyj czytelnego prefiksu klas (np.
timeline-). - Wszystkie stany wyglądają dobrze: loading, error i empty powinny być sensowne.
- Możliwość ponownego użycia bez klonowania: sprawdź, czy możesz wrzucić widżet na drugi ekran zmieniając tylko propsy i handler’y eventów, a nie kopiując wewnętrzności.
Szybły test: wyobraź sobie dodanie widżetu do ekranu admina, a potem do portalu klienta. Jeśli oba działają przy zmianie tylko propsów i obsługi eventów, jesteś w bezpiecznym miejscu.
Realistyczny przykład: dodanie widżetu timeline do dashboardu
Zespół wsparcia często chce jeden ekran, który opowie historię zgłoszenia: zmiany statusu, notatki wewnętrzne, odpowiedzi klienta i zdarzenia płatności lub dostawy. Widżet timeline pasuje idealnie, ale nie chcesz edytować generowanych plików i tracić pracy przy następnej regeneracji.
Bezpieczne podejście to trzymanie widżetu izolowanego poza generowanym UI i osadzenie go w stronie przez cienki wrapper.
Kontrakt widżetu
Trzymaj go prostym i przewidywalnym. Na przykład wrapper przekazuje:
ticketId(string)range(ostatnie 7 dni, ostatnie 30 dni, niestandardowy)mode(compact vs detailed)
Widżet emituje:
selectpo kliknięciu zdarzeniachangeFiltersgdy użytkownik zmieni zakres lub tryb
Teraz widżet nie wie nic o dashboardzie, modelach danych ani o sposobie wykonywania zapytań. Renderuje timeline i zgłasza akcje użytkownika.
Jak wrapper łączy to ze stroną
Wrapper stoi obok dashboardu i tłumaczy dane strony na kontrakt. Odczytuje aktualne ticketId ze stanu strony, konwertuje filtry UI na range i mapuje rekordy backendu na format zdarzeń oczekiwany przez widżet.
Gdy widżet emituje select, wrapper może otworzyć panel szczegółów lub wywołać akcję strony. Gdy emituje changeFilters, wrapper aktualizuje filtry strony i odświeża dane.
Gdy UI dashboardu zostanie zregenerowane, widżet pozostaje nienaruszony, bo żyje poza generowanymi plikami. Zwykle musisz zaktualizować jedynie wrapper, jeśli strona zmieniła nazwę pola lub sposób przechowywania filtrów.
Testowanie i praktyki wydawnicze, które zapobiegają niespodziankom
Niestandardowe komponenty zwykle zawodzą w nudny sposób: zmienia się kształt propsów, eventy przestają być wysyłane, albo wygenerowana strona renderuje się częściej, niż widżet oczekuje. Kilka nawyków wychwyci te problemy wcześnie.
Testy lokalne: szybko wykrywaj pęknięcia granicy
Traktuj granicę między generowanym UI a widżetem jak API. Testuj widżet bez pełnej aplikacji najpierw, używając zakodowanych propsów zgodnych z kontraktem.
Renderuj go z „happy path" i z brakującymi wartościami. Symuluj kluczowe eventy (zapisz, anuluj, select) i potwierdź, że rodzic je obsługuje. Testuj wolne dane i małe ekrany. Sprawdź, czy nie zapisuje do globalnego stanu, chyba że to część kontraktu.
Jeśli budujesz na aplikacji AppMaster Vue3, wykonaj te testy przed każdą regeneracją. Łatwiej zdiagnozować problem granicy, gdy nie zmieniasz dwóch rzeczy naraz.
Regresja po regeneracji: co sprawdzić najpierw
Po każdej regeneracji ponownie sprawdź punkty styku: czy te same propsy są przekazywane i czy te same eventy są obsługiwane? Tam zwykle pojawia się złamanie.
Utrzymuj włączenie przewidywalne. Unikaj kruchych importów zależnych od ścieżek plików, które mogą się przesunąć. Użyj jednego stabilnego punktu wejścia dla swoich komponentów niestandardowych.
Dla produkcji dodaj lekkie logowanie i przechwytywanie błędów wewnątrz widżetu:
- mounted z kluczowymi propsami (oczyszczonymi)
- naruszenia kontraktu (brak wymaganego prop, zły typ)
- nieudane wywołania API z krótkim kodem błędu
- nieoczekiwane stany puste
Gdy coś się zepsuje, chcesz szybko odpowiedzieć: czy regeneracja zmieniła wejścia, czy zmienił się widżet?
Kolejne kroki: spraw, by wzorzec był powtarzalny w całej aplikacji
Gdy pierwszy widżet działa, prawdziwym zyskiem jest uczynienie wzorca powtarzalnym, żeby następny nie był jednorazowym obejściem.
Stwórz mały wewnętrzny standard dla kontraktów widżetów i zapisz go tam, gdzie zespół trzyma notatki o aplikacji. Utrzymaj to proste: nazewnictwo, wymagane vs opcjonalne propsy, mały zestaw eventów, zachowanie wobec błędów i jasne właścicielstwo (co należy do wygenerowanego UI, a co do twojego katalogu custom).
Również zapisz zasady granicy prostym językiem: nie edytuj plików generowanych, izoluj kod niestandardowy i przekazuj dane wyłącznie przez propsy i eventy. To zapobiega „szybkiej naprawie", która przeobraża się w stały koszt utrzymania.
Zanim zbudujesz drugi widżet, przeprowadź krótką próbę regeneracji. Wypuść pierwszy widżet, potem zregeneruj co najmniej dwa razy przy normalnych zmianach (zmiana etykiety, zmiana układu, nowe pole) i potwierdź, że nic nie pęka.
Jeśli używasz AppMaster, często najlepiej trzymać większość UI i logiki w edytorach wizualnych (UI builders, Business Process Editor i Data Designer). Zostaw niestandardowe komponenty Vue na naprawdę wyjątkowe widżety, których edytory nie potrafią wyrazić, jak wyspecjalizowane timeline’y, interakcje wykresów czy nietypowe kontrolki. Jeśli chcesz czysty punkt startowy do tego podejścia, AppMaster na appmaster.io jest zaprojektowany wokół regeneracji, więc trzymanie niestandardowych widżetów izolowanych staje się naturalną częścią workflowu.
FAQ
Edycja generowanych plików Vue jest ryzykowna, ponieważ regeneracja może je całkowicie nadpisać. Nawet jeśli zmiana przetrwa raz, mała edycja w kreatorze wizualnym może odtworzyć szablony i usunąć twoje poprawki.
Umieść cały ręcznie napisany kod Vue w osobnym katalogu, którym zarządzasz (np. custom lub extensions) i importuj go jako zależność. Traktuj generowane strony jako wyjście tylko do odczytu i łącz się z komponentami przez mały, stabilny interfejs.
Wrapper to cienki komponent, który kontrolujesz i który stoi między generowaną stroną a twoim widżetem. Tłumaczy kształt danych strony na czyste propsy i zamienia eventy widżetu w akcje strony, więc gdy dane generowane zmienią się później, najczęściej aktualizujesz tylko wrapper.
Utrzymuj kontrakt mały: kilka propsów z danymi, które widżet potrzebuje, i kilka eventów do raportowania intencji użytkownika. Preferuj proste wartości i zwykłe obiekty, ustaw wartości domyślne, waliduj wejścia i w razie błędu wyświetlaj stan pusty zamiast wyrzucać wyjątek.
update:modelValue jest najlepszy, gdy widżet zachowuje się jak kontrolka formularza i ma wspierać v-model. change pasuje do potwierdzonych akcji, takich jak kliknięcie Zapisz lub zakończenie wyboru, żeby rodzic nie przetwarzał każdego naciśnięcia klawisza.
Scope’uj style widżetu i używaj wyraźnego prefiksu klas, żeby regenerowane strony przypadkowo nie nadpisywały CSS. Jeśli widżet musi dopasować się do motywu aplikacji, przekaż tokeny motywu jako propsy zamiast importować lub polegać na stylach strony.
Domyślnie trzymaj reguły biznesowe poza widżetem. Pozwól stronie lub backendowi decydować o uprawnieniach, walidacji i zachowaniu zapisu, a widżet niech skupia się na renderowaniu i interakcji oraz emituje eventy typu select, retry czy approve.
Unikaj polegania na niestabilnych szczegółach jak ścieżki plików generowanych, struktura DOM rodzica czy kształt obiektów stanu. Jeśli są konieczne, ukryj je w wrapperze, żeby zmiana nazwy pola (np. z user.name na user.profile.name) nie zmusiła cię do przepisywania widżetu.
Testuj widżet w izolacji z zakodowanymi propsami zgodnymi z kontraktem, uwzględniając brakujące i błędne wartości. Po regeneracji najpierw sprawdź dwie rzeczy: czy te same propsy są nadal przekazywane i czy te same eventy są obsługiwane przez stronę.
Kod niestandardowy jest właściwy, gdy wizualne edytory nie potrafią wyrazić wymagania: skomplikowane wykresy, selektory na mapie, panele podpisu czy narzędzia drag-and-drop. Jeśli wymaganie można zrealizować przez dopasowanie generowanego UI i procesów, będzie to zwykle łatwiejsze w utrzymaniu.


