componente de prezentare și containere
actualizare din 2019: am scris acest articol cu mult timp în urmă și opiniile mele au evoluat de atunci. În special, nu vă sugerez să vă împărțiți componentele astfel. Dacă vi se pare natural în baza de cod, acest model poate fi la îndemână. Dar am văzut-o aplicată fără nici o necesitate și cu fervoare aproape dogmatică de prea multe ori. Principalul motiv pentru care am găsit-o utilă a fost pentru că mi-a permis să separ logica stateful complexă de alte aspecte ale componentei. Hooks lasă-mă să fac același lucru fără o diviziune arbitrară. Acest text este lăsat intact din motive istorice, dar nu-l luați prea în serios.
există un model simplu pe care îl găsesc extrem de util atunci când scriu aplicații React. Dacă ați făcut reacționează pentru un timp, probabil că ați descoperit deja. Acest articol explică bine, dar vreau să adaug câteva puncte.
veți găsi componentele dvs. mult mai ușor de reutilizat și de motivat dacă le împărțiți în două categorii. Eu le numesc Container și componente de prezentare * dar am auzit, de asemenea, grăsime și slab, inteligent și prost, Stateful și pur, ecrane și Componente, etc. Toate acestea nu sunt exact la fel, dar ideea de bază este similară.
componentele mele de prezentare:
- sunt preocupați de cum arată lucrurile.
- poate conține atât componente de prezentare, cât și componente de container** în interior și, de obicei, au unele marcaje DOM și stiluri proprii.
- permit adesea izolarea prin aceasta.recuzită.copii.
- nu au dependențe de restul aplicației, cum ar fi acțiunile Flux sau magazine.
- nu specificați modul în care datele sunt încărcate sau mutate.
- primiți date și apeluri exclusiv prin recuzită.
- rareori au propria lor stare (atunci când o fac, este mai degrabă starea UI decât datele).
- sunt scrise ca componente funcționale, cu excepția cazului în care au nevoie de stare, cârlige de ciclu de viață sau optimizări de performanță.
- Exemple: Pagină, Bara Laterală, Poveste, UserInfo, Listă.
componentele containerului meu:
- sunt preocupați de modul în care funcționează lucrurile.
- pot conține atât componente de prezentare, cât și componente de container** în interior, dar de obicei nu au niciun marcaj DOM propriu, cu excepția unor div-uri de ambalare și nu au niciodată stiluri.
- furnizați datele și comportamentul componentelor de prezentare sau ale altor containere.
- apel Flux acțiuni și să furnizeze acestea ca callback la componentele de prezentare.
- sunt adesea stateful, deoarece tind să servească drept surse de date.
- sunt de obicei generate folosind componente de ordin superior, cum ar fi connect() din React Redux, createContainer() din releu sau Container.creați () din Utils Flux, mai degrabă decât scris de mână.
- Exemple: UserPage, FollowersSidebar, StoryContainer, FollowedUserList.
le-am pus în dosare diferite pentru a face această distincție clară.
beneficiile acestei abordări
- o mai bună separare a preocupărilor. Înțelegeți mai bine aplicația și interfața de utilizare scriind componente în acest fel.
- o mai bună reutilizare. Puteți utiliza aceeași componentă de prezentare cu surse de stare complet diferite și le puteți transforma în componente separate pentru containere care pot fi refolosite în continuare.
- componentele de prezentare sunt în esență “paleta”aplicației dvs. Puteți să le puneți pe o singură pagină și să lăsați designerul să-și modifice toate variațiile fără a atinge logica aplicației. Puteți rula teste de regresie a capturilor de ecran pe acea pagină.
- acest lucru vă obligă să extrageți “componente de aspect”, cum ar fi Bara laterală, pagina, ContextMenu și să utilizați acest lucru.recuzită.copiii în loc să dubleze același marcaj și aspect în mai multe componente ale containerului.
amintiți-vă, Componentele nu trebuie să emită DOM. Ei trebuie doar să ofere limite de compoziție între preocupările UI.
profită de asta.
când se introduc containerele?
vă sugerez să începeți să vă construiți aplicația doar cu componente de prezentare. În cele din urmă vă veți da seama că treceți prea multe elemente de recuzită pe componentele intermediare. Când observați că unele componente nu folosesc recuzita pe care o primesc, ci doar le transmite în jos și trebuie să rewire toate aceste componente intermediare de fiecare dată când copiii au nevoie de mai multe date, este un moment bun pentru a introduce unele componente container. În acest fel puteți obține datele și recuzita de comportament la componentele frunzelor fără a împovăra componentele care nu au legătură în mijlocul copacului.
acesta este un proces continuu de refactorizare, așa că nu încercați să-l faceți corect prima dată. Pe măsură ce experimentați acest model, veți dezvolta un simț intuitiv pentru momentul în care este timpul să extrageți unele containere, la fel cum știți când este timpul să extrageți o funcție. Seria mea gratuită Redux Egghead te-ar putea ajuta și cu asta!
alte dihotomii
este important să înțelegeți că distincția dintre componentele de prezentare și containere nu este una tehnică. Mai degrabă, este o distincție în scopul lor.
în schimb, aici sunt câteva legate (dar diferite!) distincții tehnice:
- stat și apatrid. Unele componente utilizează metoda React setState (), iar altele nu. în timp ce componentele containerului tind să fie stateful și componentele de prezentare tind să fie apatride, aceasta nu este o regulă dificilă. Componentele de prezentare pot fi stateful, iar containerele pot fi apatride.
- clase și funcții. Deoarece React 0.14, componentele pot fi declarate atât ca clase, cât și ca funcții. Componentele funcționale sunt mai simple de definit, dar le lipsesc anumite caracteristici disponibile în prezent numai pentru componentele clasei. Unele dintre aceste restricții pot dispărea în viitor, dar există astăzi. Deoarece componentele funcționale sunt mai ușor de înțeles, vă sugerez să le utilizați, cu excepția cazului în care aveți nevoie de stare, cârlige pentru ciclul de viață sau optimizări de performanță, care sunt disponibile numai pentru componentele clasei în acest moment.
- pur și impur. Oamenii spun că o componentă este pură dacă este garantată returnarea aceluiași rezultat, având în vedere aceleași elemente de recuzită și stare. Componentele Pure pot fi definite atât ca clase, cât și ca funcții și pot fi atât statale, cât și apatride. Un alt aspect important al componentelor pure este că nu se bazează pe mutații profunde în recuzită sau stare, astfel încât performanța lor de redare poate fi optimizată printr-o comparație superficială în cârligul lor shouldComponentUpdate (). În prezent, numai clasele pot defini shouldComponentUpdate (), dar care se poate schimba în viitor.
atât componentele de prezentare, cât și containerele pot cădea în oricare dintre aceste găleți. Din experiența mea, componentele de prezentare tind să fie funcții pure apatride, iar containerele tind să fie clase pure de stat. Cu toate acestea, aceasta nu este o regulă, ci o observație, și am văzut cazuri exact opuse care au avut sens în circumstanțe specifice.
nu luați separarea componentelor de prezentare și container ca o dogmă. Uneori nu contează sau este greu să tragi linia. Dacă nu vă simțiți sigur dacă o anumită componentă ar trebui să fie prezentativă sau un container, ar putea fi prea devreme pentru a decide. Nu-ți face griji!
exemplu
acest gist de Michael Chan destul de mult cuie.
lecturi suplimentare
- Noțiuni de bază cu Redux
- mixinele sunt moarte, compoziție de lungă durată
- componente Container
- Atomic Web Design
- construirea fluxului de știri Facebook cu releu
note de subsol
* într-o versiune anterioară a acestui articol le-am numit componente “inteligente” și “proaste”, dar acest lucru a fost prea dur pentru componentele de prezentare și, cel mai important, nu a explicat cu adevărat diferența în scopul lor. Îmi plac mult mai bine noii termeni și sper să o faceți și voi!
** într-o versiune anterioară a acestui articol am susținut că componentele de prezentare ar trebui să conțină numai alte componente de prezentare. Nu mai cred că acesta este cazul. Dacă o componentă este o componentă de prezentare sau un container este detaliile sale de implementare. Ar trebui să puteți înlocui o componentă de prezentare cu un container fără a modifica niciunul dintre site-urile de apel. Prin urmare, ambele componente de prezentare și container pot conține alte componente de prezentare sau container foarte bine.