React plusi un mīnusi
Kāpēc ir vērts izmantot React? Kādas ir šīs JavaScript bibliotēkas priekšrocības? Lai uzzinātu atbildes, ieskatieties šajā rakstā un atklājiet reālās priekšrocības, ko sniedz React izmantošana.
Uzziniet, kā vienkāršot un uzlabot komponentu redzamību programmā React, izmantojot nosacīto atveidošanu un aizsargkomponentus.
Šodien vēlos apspriest, kā kontrolēt komponenta redzamība React. Bet pirms mēs sākam ir mazs
atruna:
Prezentētais risinājums nav ļoti drošs, lai aizsargātu jūsu lietojumprogrammu pret "hakeriem" (lai kas tur būtu).
Atcerieties, ka jums ir jāaizsargā galapunkti un jāizmanto laba prakse lietojumprogrammu izstrādē. Šis risinājums tikai
nedaudz atvieglo jūsu darbu.
Viena no visbiežāk sastopamajām funkcijām ir rādīt komponentu tikai vairākiem lietotājiem, kuriem ir noteiktas tiesības,
lomas vai privilēģijas. Parasts risinājums ir pievienot dažas jas uz kods, manuāli pārbaudiet nosacījumus un rādiet vai nerādiet elementus.
Ļaujiet apskatīt SimpleAppHeader komponents, kas satur dažus navigācijas elementus.
<!-- wp:paragraph -->
<p><code>tipscript jsx<br>
export const SimpleAppHeader: FC = () => {<br>
return (<br>
<header><br>
<nav><br>
<ul><br>
{<br>
currentUser.role === "ADMIN" &&&<br>
<li>Tikai komponentsAdmin</li><br>
}<br>
{<br>
currentUser.role === "USER" &&<br>
<li>Tikai lietotāja komponents</li><br>
}<br>
{<br>
(currentUser.role === "ADMIN" || currentUser.role === "USER") &&<br>
<li>Tikai komponents "Administrator un lietotājs"</li><br>
}<br>
<li>Vispārējais lietošanas elements</li><br>
</ul><br>
</nav><br>
</header><br>
)<br>
}<br>
</code></p>
<!-- /wp:paragraph -->
Izskatās "nav slikti". Iespējams, lai samazinātu sarežģītību, pārbaudes varētu iekapsulēt funkcijās. currentUser ir kāds objekts
kas ir loma īpašība, bet tā var būt jebkas, ko mēs vēlamies izmantot kā kontroles mehānisma objektu.
Šim kodam ir dažas problēmas. Ja projekts aug mēs, iespējams, daudzviet lietojam šādas konstrukcijas. Tāpēc mums ir nepieciešams kopēt,
kaut kā, nosacījumi. Šo kodu ir grūti uzturēt un mainīt nākotnē. Īpaši tad, ja piekļuves noteikumi mainās
laiks, piemēram, mums ir jāmaina currentUser par kaut ko citu. To ir ļoti grūti pārbaudīt. Jums ir jāuzraksta daudzi testi.
lai pārbaudītu, vai jūsu stāvoklis ir kārtībā.
Laiks nedaudz vienkāršot šo kodu. Mēs varētu izņemt dažas metodes un padarīt kodu īsāku un mazāk sarežģītu:
const isAdmin = (role: string): boolean => role === "ADMIN";
const isUser = (role: string): boolean => role === "USER";
const isAdminOrUser = (role: string): boolean => isAdmin(role) || isUser(role);
export const SimplifiedAppHeader: FC = () => {
return (
{
isAdmin(currentUser.role) &&
Tikai administratora komponents
}
{
isUser(currentUser.role) &&
Tikai lietotāja komponents
}
{
(isAdminOrUser(currentUser.role)) &&
Tikai administratora un lietotāja komponente
}
Vispārīgas lietošanas elements
)
}
```
Izskatās daudzsološi. Mēs samazinām troksni od atkārtot līnijas. Kods ir lasāmāks un vieglāk kopjams. Bet paskatieties uz
funkcija isAdminOrUser. Mums ir tikai divas lomas. Ja mēs ieviešam trešo lomu, mums ir jāizveido vēl viens funkciju kopums.
kas apvieno lomas. Laiks uz citu versiju.
Ļaujiet ieviest funkciju hasRole kas aizstās mūsu isX funkcijas.
const hasRole = (role: string, requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => role === s);
return found !== nenoteikts;
}
export const FilteringAppHeader: FC = () => {
return (
{
hasRole(currentUser.role, ["ADMIN"]) &&
Tikai administratora komponents
}
{
hasRole(currentUser.role, ["USER"]) &&
Tikai lietotāja komponents
}
{
hasRole(currentUser.role, ["ADMIN", "USER"]) &&
Tikai administratora un lietotāja komponente
}
Vispārīgas lietošanas elements
)
}
```
Tagad izskatās labi. Mums joprojām ir nosacījumi html koda daļā, bet tagad mēs varam testēt hasRole funkciju un uzticību, ka tā
tiks izmantots pareizs parametru kopums. Tagad ir vieglāk pievienot vai mainīt lomas. Mēs izmantojam masīvu, kas satur visus
lomas, kas mums ir nepieciešamas.
Tomēr šis risinājums ir saistīts ar currentUser objekts. Pieņēmums ir tāds, ka objekts ir globāls vai viegli pieejams.
jebkurā vietā lietojumprogrammā. Tāpēc mēs varam mēģināt to iekapsulēt. Protams, mēs to varam pārvietot uz hasRole funkcija:
const hasRole = (requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => currentUser.role === s);
return found !== nenoteikts;
}
Bet tas dod mums gandrīz nekas.
Sargs SastāvdaļaLaiks izveidot komponentu, kas iekapsulē visu loģiku. Es to nosaucu Sargs un es to gribu izmantot šādi.
export const GuardedAppHeader: FC = () => {
return (
);
}
Komponentam ir nepieciešamas divas īpašības. Pirmā bērni atbildīgs par saturu, kas tiek sargāts. Otrais requiredRoles ka
apstrādāt lomu masīvu, kas mums nodrošina piekļuvi.
Mums ir nepieciešama šīs struktūras reprezentācija. Tas ir ļoti vienkārši. Mēs paplašinām tipu React.Rekvizīti ar bērniem kas ir bērni
īpašums. Protams, varat manuāli pievienot šo īpašību savam tipam un izlaist paplašinājumu.
interfeiss IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
}
Arī pats komponents ir vienkāršs. Mēs atkārtoti izmantosim hasRole funkciju šeit.
eksport const Guard = (props: IGuardProps) => {
const hasRole = (requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => currentUser.role === s);
return found !== nenoteikts;
}
if (hasRole(props.requiredRoles)) {
return (
{props.children}
);
} else {
return ;
}
}
"`
Un es varētu teikt - apstājieties šeit, bet tas būtu pārāk vienkārši. Tagad mums ir komponents, un mēs to varam izmantot līdz galējībai 😀
Pirmais solis būs pārbaužu eksternalizācija. currentUser ir cietā kodētā vērtība. Es gribētu šo vērtību iekapsulēt
kādā pakalpojumā, kas "zinās", kā pārbaudīt lomas. Tehniski tas nozīmē, ka mēs pārvietojam hasRole funkciju uz citu
klase.
Es izveidoju vienkāršu interfeisu IGuardService kam ir tikai viena īpašība - hasRole.
eksporta interfeiss IGuardService {
checkRole: (roles: string[]) => boolean;
}
Tagad vienkārša īstenošana varētu izskatīties šādi
klase SimpleGuard implementē IGuardService {
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== nenoteikts;
}
}
Lai to izmantotu, mums ir jāmaina IGuardProperties un izmantošanas gadījums.
eksportēt interfeisu IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
}
// ...
const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Tikai administratora komponente
Tikai lietotāja komponente
Administratora un lietotāja komponents
Vispārējās lietošanas elements
);
}
```
Tagad komponents izskatās šādi:
export const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) {
return (
{props.children}
);
} else {
return ;
}
}
Daudz labāk. GuardService nošķir mūs no loģikas, kas pārbauda lomas. Mēs varam to mainīt bez sekām mūsu
sastāvdaļa. Bieži sastopams gadījums, kad testos tiek izmantota maketa, bet ražošanas kodā - "īsta" implementācija.
Nākamais uzlabojums būs pielāgotu Aizliegts elements. Pašreizējais risinājums attēlo tukšu elementu. Vispirms mums ir nepieciešams
mainīt IGuardProps pievienojot funkciju, kas tiks atveidota šim elementam.
export interfeiss IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
forbidden?: () => React.ReactNode;
}
Šī ir izvēles īpašība, nosaukums beidzas ar jautājuma zīmes rakstzīmi. Tātad tā var būt funkcija vai nenoteikts. Mums ir nepieciešams
apstrādāt to Sargs sastāvdaļa.
eksport const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) {
return (
{props.children}
);
} else if (props.forbidden === nenoteikts) {
return ;
} else {
return (
{props.forbidden()}
);
}
}
// ...
export const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Tikai administratora komponente
Tikai lietotāja komponente
Aizliegts - to var redzēt tikai moderators
}>
Moderatora komponents
Administratora un lietotāja komponents
Vispārējās lietošanas elements
);
}
```
Laiks pēdējām lielajām pārmaiņām. Pašreizējā versijā komponents atbalsta tikai šādas lomas virkne. Mums varētu būt vairāki dažādi
īpašumu veidi, kurus mēs vēlamies pārbaudīt. Skaitļi vai pielāgotie tipi nav nekas īpašs. Es pievienošu vispārīgu atbalstu.
Pirmais solis ir izmaiņas IGuardService saskarne. Implementācijas būs atkarīgas no pārbaudāmās vērtības tipa. To var
būt jebkas, tāpēc interfeisam vajadzētu to apstrādāt.
eksportēt interfeisu IGuardService {
checkRole: (roles: ROLE[]) => boolean;
}
Tagad tas aizņem masīvu ROLE sugas tips. Mūsu vienkāršā implementācija nedaudz mainīsies.
klase SimpleGuard implementē IGuardService {
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== nenoteikts;
}
}
Mums ir nepieciešams pievienot tipa parametru, bet mēs varētu sagatavot implementāciju, kas atbalsta IRole saskarne.
interfeiss IRole {
name: string;
}
//...
klase RoleGuardService implementē IGuardService {
checkRole(roles: IRole[]): boolean {
let found: IRole | undefined = roles.find(e => e === userWithRole.role);
return found !== nenoteikts;
}
}
```
Otrais solis ir šo izmaiņu izplatīšana IGuardProps.
interfeiss IGuardProps extends React.PropsWithChildren {
requiredRoles: ROLE[];
guardService: IGuardService;
forbidden?: () => React.ReactNode;
}
Un attiecīgi uz Sargs sastāvdaļa.
eksport const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) {
return (
{props.children}
);
} else if (props.forbidden === nenoteikts) {
return ;
} else {
return (
{props.forbidden()}
);
}
}
Un mūsu lietošanas gadījumi
export const AppHeader: FC = () => {
const guardService = new SimpleGuard();
const roleService = new RoleGuardService();
return (
<header>
<nav>
<ul>
<Guard<IRole> requiredRoles={[{{nosaukums: "ADMIN"}]} guardService={roleService}>
<li>Tikai administratora komponents</li>
</Guard>
<Guard<string> requiredRoles={{["USER"]} guardService={GuardService}>
<li>Tikai lietotāja komponents</li>
</Guard>
<Guard<string> requiredRoles={{["MODERATOR"]} guardService={GuardService}
aizliegts={() => <div>Aizliegts - tikai moderators to var redzēt</div>}>
<li>Moderatora komponents</li>
</Guard>
<Guard<string> requiredRoles={{["USER", "ADMIN"]} guardService={GuardService}>
<li>Administratora un lietotāja komponents</li>
</Guard>
<li>Vispārīgs izmantošanas elements</li>
</ul>
</nav>
</header>
);
}
Šajā piemērā es izmantoju abas implementācijas IGuardservice tikai ilustratīviem nolūkiem. Reālos lietošanas gadījumos jūs
iespējams, izmantot tikai vienu.
Portāls Sargs varētu būt ligzdotas. Tikai atcerieties, ka piekļuve tiks atrisināta secībā no vairuma ārējo instanču.
export const NestAppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
<header>
<nav>
<ul>
<Guard<string> requiredRoles={{["USER", "ADMIN"]} guardService={GuardService}>
<Guard<string> requiredRoles={{["ADMIN"]} guardService={GuardService}>
<li>Tikai administratora komponents</li>
</Guard>
<Guard<string> requiredRoles={{["USER"]} guardService={GuardService}>
<li>Tikai lietotāja komponents</li>
</Guard>
<li>Administratora un lietotāja komponents</li>
<Guard<string> requiredRoles={{["MODERATOR"]} guardService={GuardService}
aizliegts={() => <div>Aizliegts - tikai moderators to var redzēt</div>}>
<li>Moderatora komponents</li>
</Guard>
</Guard>
<li>Vispārīgs izmantošanas elements</li>
</ul>
</nav>
</header>
);
}
Iepriekš minētajā piemērā Moderatora komponents nekad nevarētu parādīties, jo lietotājs var rīkoties tikai ar vienu lomu. Pirmais Sargs ierobežojumi
lomas, lai ADMIN un LIETOTĀJS, tāpēc MODERATORS nekad neizturēs pirmo pārbaudi.
Varam izveidot specializētus komponentus, kas slēpj dažas īpašības.
eksport const AdminGuard = (props: Omit) => {
return
{props.children}
}
//...
export const SpecializedAppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Tikai administratora komponente
Tikai lietotāja komponente
Aizliegts - to var redzēt tikai moderators
}>
Moderatora komponents
Administratora un lietotāja komponente
Vispārējās lietošanas elements
);
}
```
Šajā gadījumā AdminGuard iepriekš definēt ADMIN loma. Sekās mums ir skaidri jādefinē tips ROLE tips
parametrs.
Šajā rakstā es parādīšu, kā izveidot un izmantot Sargs React komponents. Mēs sākam ar sarežģītu kodu, ko ir grūti
lasīt un uzturēt. Mēs attīstām to vairāk izstrādātājs draudzīgu stāvokli un ieviest pielāgotu funkcionālo komponentu. Tālāk mēs
paplašināt komponentu, pievienojot papildu funkcionalitātes, refaktorizēt pakalpojuma ieguvi un visbeidzot pievienot vispārīgos tipus.
Visbeidzot, mums ir komponents, ko var ievietot, ir viegli testēt un uzturēt.
