Elementy prezentacyjne i kontenerowe

bizmut

aktualizacja z 2019: napisałem ten artykuł dawno temu i od tego czasu moje poglądy ewoluowały. W szczególności, nie sugeruję już dzielenia komponentów w ten sposób. Jeśli uważasz, że jest to naturalne w kodzie, ten wzór może być przydatny. Ale widziałem to egzekwowane bez konieczności i z niemal dogmatycznym zapałem zbyt wiele razy. Głównym powodem, dla którego uznałem to za użyteczne, było to, że pozwoliło mi oddzielić złożoną logikę stanu od innych aspektów komponentu. Hooki pozwalają mi zrobić to samo bez arbitralnego podziału. Ten tekst pozostaje nienaruszony ze względów historycznych, ale nie traktuj go zbyt poważnie.

istnieje prosty wzór, który uważam za niezwykle przydatny przy pisaniu aplikacji Reactowych. Jeśli zajmujesz się Reactem od jakiegoś czasu, prawdopodobnie już go odkryłeś. Ten artykuł dobrze to wyjaśnia, ale chcę dodać jeszcze kilka punktów.

Twoje komponenty będą znacznie łatwiejsze do ponownego użycia i rozważenia, jeśli podzielisz je na dwie kategorie. Nazywam je kontenerami i komponentami prezentacyjnymi*, ale słyszałem też grube i chude, mądre i głupie, stanowe i czyste, ekrany i komponenty itp. Te wszystkie nie są dokładnie takie same, ale podstawowa idea jest podobna.

moje prezentacje:

  • martwią się, jak to wygląda.
  • może zawierać zarówno komponenty prezentacyjne, jak i kontener** wewnątrz, i zwykle mają własne znaczniki DOM i style.
  • często Zezwalaj na przechowywanie za pomocą tego.rekwizyty.dzieci.
  • nie ma zależności od reszty aplikacji, takich jak akcje Flux lub sklepy.
  • Nie określaj, w jaki sposób dane są ładowane lub mutowane.
  • odbieraj Dane i wywołania zwrotne wyłącznie za pomocą właściwości.
  • rzadko mają swój własny stan (kiedy to robią, jest to stan interfejsu użytkownika, a nie dane).
  • są zapisywane jako komponenty funkcjonalne, chyba że wymagają stanu, hooków cyklu życia lub optymalizacji wydajności.
  • Przykłady: Strona, Pasek Boczny,Historia, UserInfo, Lista.

moje komponenty kontenera:

  • może zawierać zarówno komponenty prezentacyjne, jak i kontener** wewnątrz, ale zwykle nie mają własnych znaczników DOM, z wyjątkiem niektórych div-ów do pakowania i nigdy nie mają żadnych stylów.
  • podaj dane i zachowanie do prezentacyjnych lub innych komponentów kontenera.
  • wywołaj akcje Flux i dostarczaj je jako wywołania zwrotne do komponentów prezentacyjnych.
  • są często stateful, ponieważ mają tendencję do służyć jako źródła danych.
  • są zwykle generowane przy użyciu komponentów wyższego rzędu, takich jak connect() z React Redux, createContainer() z Relay lub Container.create() z Flux Utils, a nie napisane ręcznie.
  • Przykłady: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.

umieszczam je w różnych folderach, aby to rozróżnienie było jasne.

korzyści z tego podejścia

  • lepsze oddzielenie obaw. Pisząc w ten sposób komponenty lepiej rozumiesz swoją aplikację i interfejs użytkownika.
  • lepsza wielokrotnego użytku. Możesz użyć tego samego komponentu prezentacyjnego z zupełnie różnymi źródłami stanu i przekształcić je w oddzielne komponenty kontenera, które można ponownie wykorzystać.
  • Elementy prezentacyjne są zasadniczo “paletą”Twojej aplikacji. Możesz umieścić je na jednej stronie i pozwolić projektantowi dostosować wszystkie ich odmiany bez dotykania logiki aplikacji. Możesz uruchomić testy regresji zrzutów ekranu na tej stronie.
  • wymusza to wyodrębnienie” elementów układu”, takich jak pasek boczny, strona, ContextMenu i użycie tego.rekwizyty.dzieci zamiast powielać te same znaczniki i układ w kilku komponentach kontenera.

pamiętaj, że komponenty nie muszą emitować drzewa DOM. Muszą tylko zapewnić granice składu między obawami dotyczącymi interfejsu użytkownika.

skorzystaj z tego.

kiedy wprowadzić kontenery?

proponuję najpierw zacząć budować swoją aplikację z tylko prezentacyjnych komponentów. W końcu zdasz sobie sprawę, że przekazujesz zbyt wiele właściwości w dół pośrednich komponentów. Kiedy zauważysz, że niektóre komponenty nie używają otrzymanych właściwości, a jedynie przesuwają je w dół i musisz ponownie podłączyć wszystkie te komponenty pośrednie za każdym razem, gdy dzieci potrzebują więcej danych, jest to dobry czas na wprowadzenie niektórych komponentów kontenera. W ten sposób można uzyskać Dane i właściwości zachowania do komponentów liści bez obciążania niepowiązanych składników w środku drzewa.

jest to ciągły proces refaktoryzacji, więc nie próbuj go naprawić za pierwszym razem. Eksperymentując z tym wzorem, rozwijasz intuicyjne wyczucie, kiedy nadszedł czas na wyodrębnienie niektórych kontenerów, tak jak wiesz, kiedy nadszedł czas na wyodrębnienie funkcji. Moja Darmowa Seria Redux Egghead może Ci w tym pomóc!

Inne dychotomie

ważne jest, abyś zrozumiał, że różnica między komponentami prezentacyjnymi a kontenerami nie jest techniczna. Jest to raczej rozróżnienie w ich celu.

dla kontrastu, oto kilka powiązanych (ale innych!) wyróżnienia techniczne:

  • Stanowy i Bezpaństwowy. Niektóre komponenty używają metody react setState (), a inne nie. podczas gdy komponenty kontenerów mają tendencję do stanu, a komponenty prezentacyjne mają tendencję do stanu, nie jest to trudna zasada. Komponenty prezentacyjne mogą być stanowe, a kontenery mogą być również bezstanowe.
  • klasy i funkcje. Od Reacta 0.14 komponenty mogą być deklarowane zarówno jako klasy, jak i jako funkcje. Komponenty funkcjonalne są prostsze do zdefiniowania, ale brakuje im pewnych funkcji dostępnych obecnie tylko dla komponentów klasowych. Niektóre z tych ograniczeń mogą zniknąć w przyszłości, ale istnieją już dzisiaj. Ponieważ komponenty funkcjonalne są łatwiejsze do zrozumienia, sugeruję ich użycie, chyba że potrzebujesz stanu, hooków cyklu życia lub optymalizacji wydajności, które są obecnie dostępne tylko dla komponentów klasy.
  • czysty i nieczysty. Ludzie mówią, że składnik jest czysty, jeśli ma gwarancję, że zwróci ten sam wynik, biorąc pod uwagę te same właściwości i stan. Czyste komponenty mogą być definiowane zarówno jako klasy, jak i funkcje, i mogą być zarówno stateczne, jak i bezstanowe. Innym ważnym aspektem czystych komponentów jest to, że nie polegają one na głębokich mutacjach w właściwościach lub stanie, więc ich wydajność renderowania może być zoptymalizowana przez płytkie porównanie w hooku shouldComponentUpdate (). Obecnie tylko klasy mogą zdefiniować shouldcomponentupdate (), ale to może się zmienić w przyszłości.

zarówno komponenty prezentacyjne, jak i kontenery mogą wpaść do jednego z tych wiadrów. Z mojego doświadczenia wynika, że komponenty prezentacyjne są zwykle czystymi funkcjami bezstanowymi, a kontenery są czystymi klasami stanu. Jednak nie jest to reguła, ale obserwacja, i widziałem dokładnie odwrotne przypadki, które miały sens w konkretnych okolicznościach.

nie traktuj separacji elementów prezentacyjnych i kontenerowych jako dogmatu. Czasami nie ma to znaczenia lub trudno jest wyznaczyć granicę. Jeśli nie masz pewności, czy konkretny komponent powinien być prezentacyjny, czy kontener, może być zbyt wcześnie, aby zdecydować. Nie przejmuj się!

przykład

ten gist autorstwa Michaela Chana całkiem nieźle.

Czytaj dalej

  • Wprowadzenie do Redux
  • mixins are Dead, Long Live Composition
  • Komponenty kontenerowe
  • Atomic Web Design
  • budowanie kanału informacyjnego na Facebooku za pomocą przekaźnika

Przypisy

* we wcześniejszej wersji tego artykułu nazwałem je” inteligentnymi “i” głupimi ” komponentami, ale było to zbyt surowe dla prezentowanych komponentów i, co najważniejsze, nie wyjaśniało różnicy w ich przeznaczeniu. Nowe warunki podobają mi się znacznie lepiej i mam nadzieję, że ty też!

* * we wcześniejszej wersji tego artykułu twierdziłem, że komponenty prezentacyjne powinny zawierać tylko inne komponenty prezentacyjne. Już tak nie jest. To, czy komponent jest komponentem prezentacyjnym, czy kontenerem, jest szczegółem jego implementacji. Powinieneś być w stanie zastąpić komponent prezentacyjny kontenerem bez modyfikowania żadnego z witryn połączeń. Dlatego zarówno komponenty prezentacyjne, jak i kontenerowe mogą zawierać inne komponenty prezentacyjne lub kontenerowe.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.