Išnagrinėkite React Children įrankius, skirtus efektyviam vaikinių elementų valdymui. Išmokite geriausių praktikų, kad sukurtumėte dinamiškas React aplikacijas.
React Children įrankių įvaldymo menas: išsamus vadovas
React komponentų modelis yra nepaprastai galingas, leidžiantis kūrėjams kurti sudėtingas vartotojo sąsajas iš daugkartinio naudojimo blokų. Šio modelio pagrindas yra „children“ (vaikinių elementų) koncepcija – elementai, perduodami tarp komponento atidarymo ir uždarymo žymių. Nors iš pirmo žvilgsnio tai atrodo paprasta, efektyvus šių vaikinių elementų valdymas ir manipuliavimas yra labai svarbus kuriant dinamiškas ir lanksčias aplikacijas. React pateikia įrankių rinkinį React.Children API, specialiai sukurtą šiam tikslui. Šiame išsamiame vadove nuodugniai išnagrinėsime šiuos įrankius, pateiksime praktinių pavyzdžių ir geriausių praktikų, kurios padės jums įvaldyti vaikinių elementų manipuliavimą ir iteraciją React aplinkoje.
Kas yra React Children?
React aplinkoje „children“ (vaikiniai elementai) reiškia turinį, kurį komponentas gauna tarp savo atidarymo ir uždarymo žymių. Šis turinys gali būti bet kas – nuo paprasto teksto iki sudėtingų komponentų hierarchijų. Apsvarstykite šį pavyzdį:
<MyComponent>
<p>Tai yra vaikinis elementas.</p>
<AnotherComponent />
</MyComponent>
Komponento MyComponent viduje props.children savybė turės šiuos du elementus: <p> elementą ir <AnotherComponent /> egzempliorių. Tačiau tiesioginis props.children naudojimas ir manipuliavimas gali būti sudėtingas, ypač dirbant su potencialiai sudėtingomis struktūromis. Būtent čia į pagalbą ateina React.Children įrankiai.
React.Children API: jūsų įrankių rinkinys vaikinių elementų valdymui
React.Children API suteikia statinių metodų rinkinį, skirtą iteruoti ir transformuoti props.children nepermatomą duomenų struktūrą. Šie įrankiai suteikia patikimesnį ir standartizuotą būdą tvarkyti vaikinius elementus, palyginti su tiesioginiu props.children naudojimu.
1. React.Children.map(children, fn, thisArg?)
React.Children.map() yra bene dažniausiai naudojamas įrankis. Jis yra analogiškas standartiniam JavaScript Array.prototype.map() metodui. Jis iteruoja per kiekvieną tiesioginį children savybės vaikinį elementą ir kiekvienam pritaiko pateiktą funkciją. Rezultatas yra nauja kolekcija (dažniausiai masyvas), kurioje yra transformuoti vaikiniai elementai. Svarbu paminėti, kad jis veikia tik su *tiesioginiais* vaikiniais elementais, o ne su anūkais ar giliau esančiais palikuonimis.
Pavyzdys: bendro klasės pavadinimo pridėjimas visiems tiesioginiams vaikiniams elementams
function MyComponent(props) {
return (
<div className="my-component">
{React.Children.map(props.children, (child) => {
// React.isValidElement() apsaugo nuo klaidų, kai vaikinys yra eilutė ar skaičius.
if (React.isValidElement(child)) {
return React.cloneElement(child, {
className: child.props.className ? child.props.className + ' common-class' : 'common-class',
});
} else {
return child;
}
})}
</div>
);
}
// Naudojimas:
<MyComponent>
<div className="existing-class">Vaikas 1</div>
<span>Vaikas 2</span>
</MyComponent>
Šiame pavyzdyje React.Children.map() iteruoja per MyComponent vaikinius elementus. Kiekvienam vaikiniam elementui jis klonuoja elementą naudodamas React.cloneElement() ir prideda klasės pavadinimą „common-class“. Galutinė išvestis būtų:
<div className="my-component">
<div className="existing-class common-class">Vaikas 1</div>
<span className="common-class">Vaikas 2</span>
</div>
Svarbūs aspektai naudojant React.Children.map():
keysavybė: Kai iteruojate per vaikinius elementus ir grąžinate naujus elementus, visada užtikrinkite, kad kiekvienas elementas turėtų unikalųkeyatributą. Tai padeda React efektyviai atnaujinti DOM.- Grąžinamas
null: Galite grąžintinulliš `map` funkcijos, kad išfiltruotumėte konkrečius vaikinius elementus. - Ne elementų tipo vaikinių elementų tvarkymas: Vaikiniai elementai gali būti eilutės, skaičiai ar net
null/undefined. NaudokiteReact.isValidElement(), kad užtikrintumėte, jog klonuojate ir modifikuojate tik React elementus.
2. React.Children.forEach(children, fn, thisArg?)
React.Children.forEach() yra panašus į React.Children.map(), tačiau jis negrąžina naujos kolekcijos. Vietoj to, jis tiesiog iteruoja per vaikinius elementus ir įvykdo pateiktą funkciją kiekvienam elementui. Jis dažnai naudojamas šalutiniams efektams atlikti ar informacijai apie vaikinius elementus rinkti.
Pavyzdys: <li> elementų skaičiavimas tarp vaikinių elementų
function MyComponent(props) {
let liCount = 0;
React.Children.forEach(props.children, (child) => {
if (child && child.type === 'li') {
liCount++;
}
});
return (
<div>
<p><li> elementų skaičius: {liCount}</p>
{props.children}
</div>
);
}
// Naudojimas:
<MyComponent>
<ul>
<li>Elementas 1</li>
<li>Elementas 2</li>
<li>Elementas 3</li>
</ul>
<p>Kitas turinys</p>
</MyComponent>
Šiame pavyzdyje React.Children.forEach() iteruoja per vaikinius elementus ir padidina liCount kiekvienam rastam <li> elementui. Tada komponentas atvaizduoja <li> elementų skaičių.
Pagrindiniai skirtumai tarp React.Children.map() ir React.Children.forEach():
React.Children.map()grąžina naują modifikuotų vaikinių elementų masyvą;React.Children.forEach()nieko negrąžina.React.Children.map()paprastai naudojamas vaikinių elementų transformavimui;React.Children.forEach()naudojamas šalutiniams efektams ar informacijos rinkimui.
3. React.Children.count(children)
React.Children.count() grąžina tiesioginių vaikinių elementų skaičių children savybėje. Tai paprastas, bet naudingas įrankis, skirtas nustatyti vaikinių elementų kolekcijos dydį.
Pavyzdys: vaikinių elementų skaičiaus rodymas
function MyComponent(props) {
const childCount = React.Children.count(props.children);
return (
<div>
<p>Šis komponentas turi {childCount} vaikinius elementus.</p>
{props.children}
</div>
);
}
// Naudojimas:
<MyComponent>
<div>Vaikas 1</div>
<span>Vaikas 2</span>
<p>Vaikas 3</p>
</MyComponent>
Šiame pavyzdyje React.Children.count() grąžina 3, nes komponentui MyComponent perduodami trys tiesioginiai vaikiniai elementai.
4. React.Children.toArray(children)
React.Children.toArray() konvertuoja children savybę (kuri yra nepermatoma duomenų struktūra) į standartinį JavaScript masyvą. Tai gali būti naudinga, kai reikia atlikti masyvams būdingas operacijas su vaikiniais elementais, pavyzdžiui, rūšiuoti ar filtruoti.
Pavyzdys: vaikinių elementų eiliškumo apvertimas
function MyComponent(props) {
const childrenArray = React.Children.toArray(props.children);
const reversedChildren = childrenArray.reverse();
return (
<div>
{reversedChildren}
</div>
);
}
// Naudojimas:
<MyComponent>
<div>Vaikas 1</div>
<span>Vaikas 2</span>
<p>Vaikas 3</p>
</MyComponent>
Šiame pavyzdyje React.Children.toArray() konvertuoja vaikinius elementus į masyvą. Tada masyvas apverčiamas naudojant Array.prototype.reverse(), ir atvaizduojami apversti vaikiniai elementai.
Svarbūs aspektai naudojant React.Children.toArray():
- Gautam masyvui kiekvienam elementui bus priskirti raktai (keys), gauti iš originalių raktų arba sugeneruoti automatiškai. Tai užtikrina, kad React galės efektyviai atnaujinti DOM net ir po masyvo manipuliacijų.
- Nors galite atlikti bet kokią masyvo operaciją, atminkite, kad tiesioginis vaikinių elementų masyvo modifikavimas gali sukelti netikėtą elgesį, jei nesate atsargūs.
Pažangios technikos ir geriausios praktikos
1. React.cloneElement() naudojimas vaikinių elementų modifikavimui
Kai reikia modifikuoti vaikinio elemento savybes, paprastai rekomenduojama naudoti React.cloneElement(). Ši funkcija sukuria naują React elementą, pagrįstą esamu elementu, leidžiant jums perrašyti ar pridėti naujų savybių tiesiogiai nemutuojant originalaus elemento. Tai padeda išlaikyti nekintamumą ir išvengti netikėtų šalutinių poveikių.
Pavyzdys: konkrečios savybės pridėjimas visiems vaikiniams elementams
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { customProp: 'Sveiki iš MyComponent' });
} else {
return child;
}
})}
</div>
);
}
// Naudojimas:
<MyComponent>
<div>Vaikas 1</div>
<span>Vaikas 2</span>
</MyComponent>
Šiame pavyzdyje React.cloneElement() naudojamas norint pridėti customProp kiekvienam vaikiniam elementui. Gauti elementai turės šią savybę prieinamą savo savybių objekte.
2. Darbas su fragmentuotais vaikiniais elementais
React fragmentai (<></> arba <React.Fragment></React.Fragment>) leidžia sugrupuoti kelis vaikinius elementus nepridedant papildomo DOM mazgo. React.Children įrankiai elegantiškai tvarko fragmentus, traktuodami kiekvieną fragmento viduje esantį elementą kaip atskirą vaikinį elementą.
Pavyzdys: iteracija per vaikinius elementus Fragmente
function MyComponent(props) {
React.Children.forEach(props.children, (child) => {
console.log(child);
});
return <div>{props.children}</div>;
}
// Naudojimas:
<MyComponent>
<>
<div>Vaikas 1</div>
<span>Vaikas 2</span>
</>
<p>Vaikas 3</p>
</MyComponent>
Šiame pavyzdyje React.Children.forEach() funkcija iteruos per tris vaikinius elementus: <div> elementą, <span> elementą ir <p> elementą, nors pirmieji du yra apgaubti Fragmentu.
3. Skirtingų tipų vaikinių elementų tvarkymas
Kaip minėta anksčiau, vaikiniai elementai gali būti React elementai, eilutės, skaičiai ar net null/undefined. Svarbu tinkamai tvarkyti šiuos skirtingus tipus savo React.Children įrankių funkcijose. React.isValidElement() naudojimas yra labai svarbus norint atskirti React elementus nuo kitų tipų.
Pavyzdys: skirtingo turinio atvaizdavimas priklausomai nuo vaikinio elemento tipo
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return <div className="element-child">{child}</div>;
} else if (typeof child === 'string') {
return <div className="string-child">Eilutė: {child}</div>;
} else if (typeof child === 'number') {
return <div className="number-child">Skaičius: {child}</div>;
} else {
return null;
}
})}
</div>
);
}
// Naudojimas:
<MyComponent>
<div>Vaikas 1</div>
"Tai yra eilutės tipo vaikas"
123
</MyComponent>
Šis pavyzdys parodo, kaip tvarkyti skirtingų tipų vaikinius elementus, atvaizduojant juos su specifiniais klasių pavadinimais. Jei vaikas yra React elementas, jis apgaubiamas <div> su klase „element-child“. Jei tai eilutė, jis apgaubiamas <div> su klase „string-child“ ir t. t.
4. Gilusis vaikinių elementų perėjimas (naudokite atsargiai!)
React.Children įrankiai veikia tik su tiesioginiais vaikiniais elementais. Jei jums reikia pereiti per visą komponentų medį (įskaitant anūkus ir gilesnius palikuonis), turėsite įgyvendinti rekursyvinę perėjimo funkciją. Tačiau būkite labai atsargūs tai darydami, nes tai gali būti skaičiavimo atžvilgiu brangu ir gali rodyti dizaino trūkumą jūsų komponentų struktūroje.
Pavyzdys: rekursyvinis vaikinių elementų perėjimas
function traverseChildren(children, callback) {
React.Children.forEach(children, (child) => {
callback(child);
if (React.isValidElement(child) && child.props.children) {
traverseChildren(child.props.children, callback);
}
});
}
function MyComponent(props) {
traverseChildren(props.children, (child) => {
console.log(child);
});
return <div>{props.children}</div>;
}
// Naudojimas:
<MyComponent>
<div>
<span>Vaikas 1</span>
<p>Vaikas 2</p>
</div>
<p>Vaikas 3</p>
</MyComponent>
Šiame pavyzdyje apibrėžiama traverseChildren() funkcija, kuri rekursyviai iteruoja per vaikinius elementus. Ji iškviečia pateiktą atgalinio ryšio funkciją (callback) kiekvienam vaikui ir tada rekursyviai iškviečia save bet kuriam vaikui, kuris turi savo vaikinių elementų. Dar kartą, naudokite šį metodą saikingai ir tik esant būtinybei. Apsvarstykite alternatyvius komponentų dizainus, kurie išvengia gilaus perėjimo.
Internacionalizacija (i18n) ir React Children
Kuriant aplikacijas pasaulinei auditorijai, apsvarstykite, kaip React.Children įrankiai sąveikauja su internacionalizacijos bibliotekomis. Pavyzdžiui, jei naudojate biblioteką, tokią kaip react-intl ar i18next, gali tekti koreguoti, kaip iteruojate per vaikinius elementus, kad užtikrintumėte teisingą lokalizuotų eilučių atvaizdavimą.
Pavyzdys: react-intl naudojimas su React.Children.map()
import { FormattedMessage } from 'react-intl';
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child, index) => {
if (typeof child === 'string') {
// Apgaubkite eilutės tipo vaikinius elementus su FormattedMessage
return <FormattedMessage id={`myComponent.child${index + 1}`} defaultMessage={child} />;
} else {
return child;
}
})}
</div>
);
}
// Apibrėžkite vertimus savo lokalizacijos failuose (pvz., en.json, fr.json):
// {
// "myComponent.child1": "Išverstas vaikas 1",
// "myComponent.child2": "Išverstas vaikas 2"
// }
// Naudojimas:
<MyComponent>
"Vaikas 1"
<div>Koks nors elementas</div>
"Vaikas 2"
</MyComponent>
Šis pavyzdys rodo, kaip apgaubti eilutės tipo vaikinius elementus <FormattedMessage> komponentais iš react-intl. Tai leidžia pateikti lokalizuotas eilutės tipo vaikinių elementų versijas, atsižvelgiant į vartotojo lokalę. id savybė <FormattedMessage> turėtų atitikti raktą jūsų lokalizacijos failuose.
Dažniausi panaudojimo atvejai
- Maketo komponentai: daugkartinio naudojimo maketo komponentų kūrimas, kurie gali priimti bet kokį turinį kaip vaikinius elementus.
- Meniu komponentai: dinamiškas meniu punktų generavimas pagal komponentui perduotus vaikinius elementus.
- Kortelių (tabs) komponentai: aktyvios kortelės valdymas ir atitinkamo turinio atvaizdavimas pagal pasirinktą vaikinį elementą.
- Modalinių langų komponentai: vaikinių elementų apgaubimas modaliniam langui būdingu stiliumi ir funkcionalumu.
- Formų komponentai: iteravimas per formos laukus ir bendro tikrinimo ar stiliaus taikymas.
Išvados
React.Children API yra galingas įrankių rinkinys, skirtas valdyti ir manipuliuoti vaikiniais elementais React komponentuose. Suprasdami šiuos įrankius ir taikydami šiame vadove aprašytas geriausias praktikas, galite sukurti lankstesnius, daugkartinio naudojimo ir lengviau prižiūrimus komponentus. Nepamirškite naudoti šių įrankių apdairiai ir visada atsižvelkite į sudėtingų vaikinių elementų manipuliacijų našumo pasekmes, ypač dirbant su dideliais komponentų medžiais. Pasinaudokite React komponentų modelio galia ir kurkite nuostabias vartotojo sąsajas pasaulinei auditorijai!
Įvaldę šias technikas, galėsite rašyti tvirtesnes ir labiau pritaikomas React aplikacijas. Nepamirškite savo kūrimo procese teikti pirmenybę kodo aiškumui, našumui ir priežiūrai. Sėkmės programuojant!