Atklājiet React portālu spēku, lai izveidotu pieejamus un vizuāli pievilcīgus modālos logus un rīka padomus, uzlabojot lietotāja pieredzi un komponentu struktūru.
React portāli: modālo logu un rīka padomu apgūšana uzlabotai lietotāja pieredzei (UX)
Mūsdienu tīmekļa izstrādē intuitīvu un saistošu lietotāja saskarņu veidošana ir ļoti svarīga. React, populāra JavaScript bibliotēka lietotāja saskarņu veidošanai, nodrošina dažādus rīkus un tehnikas, lai to sasniegtu. Viens no šādiem spēcīgiem rīkiem ir React portāli. Šis emuāra ieraksts iedziļinās React portālu pasaulē, koncentrējoties uz to pielietojumu pieejamu un vizuāli pievilcīgu modālo logu un rīka padomu veidošanā.
Kas ir React portāli?
React portāli piedāvā veidu, kā renderēt komponenta bērnelementus DOM mezglā, kas atrodas ārpus vecāka komponenta DOM hierarhijas. Vienkāršāk sakot, tas ļauj jums atbrīvoties no standarta React komponentu koka un ievietot elementus tieši citā HTML struktūras daļā. Tas ir īpaši noderīgi situācijās, kad nepieciešams kontrolēt elementu novietošanas kontekstu (stacking context) vai pozicionēt elementus ārpus to vecāka konteinera robežām.
Tradicionāli React komponenti tiek renderēti kā to vecāku komponentu bērni DOM ietvaros. Tas dažkārt var radīt stila un izkārtojuma problēmas, īpaši strādājot ar tādiem elementiem kā modālie logi vai rīka padomi, kuriem jāparādās virs cita satura vai jābūt pozicionētiem attiecībā pret skatlogu. React portāli nodrošina risinājumu, ļaujot šos elementus renderēt tieši citā DOM koka daļā, tādējādi apejot šos ierobežojumus.
Kāpēc izmantot React portālus?
Vairākas galvenās priekšrocības padara React portālus par vērtīgu rīku jūsu React izstrādes arsenālā:
- Uzlabots stils un izkārtojums: Portāli ļauj pozicionēt elementus ārpus to vecāka konteinera, pārvarot stila problēmas, ko izraisa
overflow: hidden,z-indexierobežojumi vai sarežģīti izkārtojuma nosacījumi. Iedomājieties modālo logu, kuram jāpārklāj viss ekrāns, pat ja tā vecāka konteineram ir iestatītsoverflow: hidden. Portāli ļauj renderēt modālo logu tiešibodyelementā, apejot šo ierobežojumu. - Uzlabota pieejamība: Portāli ir būtiski pieejamībai, īpaši strādājot ar modālajiem logiem. Renderējot modālā loga saturu tieši
bodyelementā, jūs varat viegli pārvaldīt fokusa "ieslodzīšanu" (focus trapping), nodrošinot, ka lietotāji, kas izmanto ekrāna lasītājus vai tastatūras navigāciju, paliek modālā loga ietvaros, kamēr tas ir atvērts. Tas ir būtiski, lai nodrošinātu netraucētu un pieejamu lietotāja pieredzi. - Tīrāka komponentu struktūra: Renderējot modālā loga vai rīka padoma saturu ārpus galvenā komponentu koka, jūs varat uzturēt savu komponentu struktūru tīrāku un vieglāk pārvaldāmu. Šī atbildības jomu nodalīšana var padarīt jūsu kodu vieglāk lasāmu, saprotamu un uzturamu.
- Izvairīšanās no "stacking context" problēmām: "Stacking context" CSS var būt bēdīgi slavens ar savu sarežģītību. Portāli palīdz izvairīties no šīm problēmām, ļaujot renderēt elementus tieši DOM saknē, nodrošinot, ka tie vienmēr ir pareizi pozicionēti attiecībā pret citiem lapas elementiem.
Modālo logu ieviešana ar React portāliem
Modālie logi ir izplatīts lietotāja saskarnes modelis, ko izmanto, lai parādītu svarīgu informāciju vai pieprasītu lietotāja ievadi. Apskatīsim, kā izveidot modālo logu, izmantojot React portālus.
1. Portāla saknes izveide
Vispirms jums ir jāizveido DOM mezgls, kurā tiks renderēts modālais logs. To parasti dara, pievienojot div elementu ar konkrētu ID jūsu HTML failam (parasti body elementā):
<div id="modal-root"></div>
2. Modālā loga komponenta izveide
Tālāk izveidojiet React komponentu, kas attēlos modālo logu. Šis komponents saturēs modālā loga saturu un loģiku.
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
const Modal = ({ isOpen, onClose, children }) => {
const [mounted, setMounted] = useState(false);
const modalRoot = useRef(document.getElementById('modal-root'));
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
if (!isOpen) return null;
const modalContent = (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
{children}
<button onClick={onClose}>Close</button>
</div>
</div>
);
return mounted && modalRoot.current
? ReactDOM.createPortal(modalContent, modalRoot.current)
: null;
};
export default Modal;
Paskaidrojums:
isOpenprops: Nosaka, vai modālais logs ir redzams.onCloseprops: Funkcija modālā loga aizvēršanai.childrenprops: Saturs, kas tiks parādīts modālā loga iekšpusē.modalRootref: Atsauce uz DOM mezglu, kurā tiks renderēts modālais logs (#modal-root).useEffectāķis: Nodrošina, ka modālais logs tiek renderēts tikai pēc komponenta ielādes (mount), lai izvairītos no problēmām, kad portāla sakne nav uzreiz pieejama.ReactDOM.createPortal: Šī ir React portālu lietošanas atslēga. Tā pieņem divus argumentus: React elementu, ko renderēt (modalContent), un DOM mezglu, kurā tas jārenderē (modalRoot.current).- Klikšķis uz pārklājuma: Aizver modālo logu. Mēs izmantojam
e.stopPropagation()uzmodal-contentdiv, lai novērstu, ka klikšķi modālā loga iekšpusē to aizver.
3. Modālā loga komponenta izmantošana
Tagad jūs varat izmantot Modal komponentu savā lietotnē:
import React, { useState } from 'react';
import Modal from './Modal';
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
return (
<div>
<button onClick={openModal}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={closeModal}>
<h2>Modal Content</h2>
<p>This is the content of the modal.</p>
</Modal>
</div>
);
};
export default App;
Šis piemērs demonstrē, kā kontrolēt modālā loga redzamību, izmantojot isOpen props un openModal un closeModal funkcijas. Saturs, kas atrodas <Modal> tagos, tiks renderēts modālā loga iekšpusē.
4. Modālā loga stilizēšana
Pievienojiet CSS stilus, lai pozicionētu un stilizētu modālo logu. Šeit ir vienkāršs piemērs:
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
display: flex;
justify-content: center;
align-items: center;
z-index: 1000; /* Ensure it's on top of other content */
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
CSS paskaidrojums:
position: fixed: Nodrošina, ka modālais logs pārklāj visu skatlogu, neatkarīgi no ritināšanas.background-color: rgba(0, 0, 0, 0.5): Izveido daļēji caurspīdīgu pārklājumu aiz modālā loga.display: flex, justify-content: center, align-items: center: Centrē modālo logu horizontāli un vertikāli.z-index: 1000: Nodrošina, ka modālais logs tiek renderēts virs visiem citiem lapas elementiem.
5. Pieejamības apsvērumi modālajiem logiem
Pieejamība ir ļoti svarīga, ieviešot modālos logus. Šeit ir daži galvenie apsvērumi:
- Fokusa pārvaldība: Kad modālais logs tiek atvērts, fokusam automātiski jāpāriet uz elementu modālā loga iekšienē (piemēram, pirmo ievades lauku vai aizvēršanas pogu). Kad modālais logs tiek aizvērts, fokusam jāatgriežas pie elementa, kas izraisīja modālā loga atvēršanu. To bieži panāk, izmantojot React
useRefāķi, lai saglabātu iepriekš fokusēto elementu. - Tastatūras navigācija: Nodrošiniet, ka lietotāji var pārvietoties pa modālo logu, izmantojot tastatūru (Tab taustiņu). Fokusam jābūt "ieslodzītam" modālā loga ietvaros, neļaujot lietotājiem nejauši iziet no tā ar Tab taustiņu. Ar to var palīdzēt tādas bibliotēkas kā
react-focus-lock. - ARIA atribūti: Izmantojiet ARIA atribūtus, lai sniegtu semantisku informāciju par modālo logu ekrāna lasītājiem. Piemēram, izmantojiet
aria-modal="true"uz modālā loga konteinera unaria-labelvaiaria-labelledby, lai nodrošinātu aprakstošu etiķeti modālajam logam. - Aizvēršanas mehānisms: Nodrošiniet vairākus veidus, kā aizvērt modālo logu, piemēram, aizvēršanas pogu, klikšķi uz pārklājuma vai Escape taustiņa nospiešanu.
Fokusa pārvaldības piemērs (izmantojot useRef):
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
const Modal = ({ isOpen, onClose, children }) => {
const [mounted, setMounted] = useState(false);
const modalRoot = useRef(document.getElementById('modal-root'));
const firstFocusableElement = useRef(null);
const previouslyFocusedElement = useRef(null);
useEffect(() => {
setMounted(true);
if (isOpen) {
previouslyFocusedElement.current = document.activeElement;
if (firstFocusableElement.current) {
firstFocusableElement.current.focus();
}
const handleKeyDown = (event) => {
if (event.key === 'Escape') {
onClose();
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
if (previouslyFocusedElement.current) {
previouslyFocusedElement.current.focus();
}
};
}
return () => setMounted(false);
}, [isOpen, onClose]);
if (!isOpen) return null;
const modalContent = (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2>Modal Content</h2>
<p>This is the content of the modal.</p>
<input type="text" ref={firstFocusableElement} /> <!-- First focusable element -->
<button onClick={onClose}>Close</button>
</div>
</div>
);
return mounted && modalRoot.current
? ReactDOM.createPortal(modalContent, modalRoot.current)
: null;
};
export default Modal;
Fokusa pārvaldības koda paskaidrojums:
previouslyFocusedElement.current: Saglabā elementu, kuram bija fokuss pirms modālā loga atvēršanas.firstFocusableElement.current: Atsauce uz pirmo fokusējamo elementu *iekšpusē* modālā loga (šajā piemērā teksta ievades lauks).- Kad modālais logs atveras (
isOpenir patiess):- Pašreizējais fokusētais elements tiek saglabāts.
- Fokuss tiek pārvietots uz
firstFocusableElement.current. - Tiek pievienots notikumu klausītājs, lai reaģētu uz Escape taustiņu, aizverot modālo logu.
- Kad modālais logs aizveras (tīrīšanas funkcija):
- Escape taustiņa notikumu klausītājs tiek noņemts.
- Fokuss tiek atgriezts elementam, kas bija iepriekš fokusēts.
Rīka padomu ieviešana ar React portāliem
Rīka padomi ir mazi, informatīvi uznirstošie logi, kas parādās, kad lietotājs virza kursoru virs kāda elementa. React portālus var izmantot, lai izveidotu rīka padomus, kas ir pareizi pozicionēti neatkarīgi no vecāka elementa stila vai izkārtojuma.
1. Portāla saknes izveide (ja vēl nav izveidota)
Ja jūs vēl neesat izveidojis portāla sakni modālajiem logiem, pievienojiet div elementu ar konkrētu ID jūsu HTML failam (parasti body elementā):
<div id="tooltip-root"></div>
2. Rīka padoma komponenta izveide
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
const Tooltip = ({ text, children, position = 'top' }) => {
const [isVisible, setIsVisible] = useState(false);
const [positionStyle, setPositionStyle] = useState({});
const [mounted, setMounted] = useState(false);
const tooltipRoot = useRef(document.getElementById('tooltip-root'));
const tooltipRef = useRef(null);
const triggerRef = useRef(null);
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
const handleMouseEnter = () => {
setIsVisible(true);
updatePosition();
};
const handleMouseLeave = () => {
setIsVisible(false);
};
const updatePosition = () => {
if (!triggerRef.current || !tooltipRef.current) return;
const triggerRect = triggerRef.current.getBoundingClientRect();
const tooltipRect = tooltipRef.current.getBoundingClientRect();
let top = 0;
let left = 0;
switch (position) {
case 'top':
top = triggerRect.top - tooltipRect.height - 5; // 5px spacing
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
break;
case 'bottom':
top = triggerRect.bottom + 5;
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
break;
case 'left':
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
left = triggerRect.left - tooltipRect.width - 5;
break;
case 'right':
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
left = triggerRect.right + 5;
break;
default:
break;
}
setPositionStyle({
top: `${top}px`,
left: `${left}px`,
});
};
const tooltipContent = isVisible && (
<div className="tooltip" style={positionStyle} ref={tooltipRef}>
{text}
</div>
);
return (
<span
ref={triggerRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{children}
{mounted && tooltipRoot.current ? ReactDOM.createPortal(tooltipContent, tooltipRoot.current) : null}
</span>
);
};
export default Tooltip;
Paskaidrojums:
textprops: Teksts, kas jāattēlo rīka padomā.childrenprops: Elements, kas izraisa rīka padoma parādīšanos (elements, virs kura lietotājs virza kursoru).positionprops: Rīka padoma pozīcija attiecībā pret izsaucējelementu ('top', 'bottom', 'left', 'right'). Noklusējuma vērtība ir 'top'.isVisiblestāvoklis: Kontrolē rīka padoma redzamību.tooltipRootref: Atsauce uz DOM mezglu, kurā tiks renderēts rīka padoms (#tooltip-root).tooltipRefref: Atsauce uz pašu rīka padoma elementu, ko izmanto tā izmēru aprēķināšanai.triggerRefref: Atsauce uz elementu, kas izraisa rīka padomu (children).handleMouseEnterunhandleMouseLeave: Notikumu apstrādātāji kursora virzīšanai virs izsaucējelementa.updatePosition: Aprēķina pareizo rīka padoma pozīciju, pamatojoties uzpositionprops un izsaucējelementa un rīka padoma elementu izmēriem. Tā izmantogetBoundingClientRect(), lai iegūtu elementu pozīciju un izmērus attiecībā pret skatlogu.ReactDOM.createPortal: Renderē rīka padoma saturutooltipRootelementā.
3. Rīka padoma komponenta izmantošana
import React from 'react';
import Tooltip from './Tooltip';
const App = () => {
return (
<div>
<p>
Hover over this <Tooltip text="This is a tooltip!
With multiple lines."
position="bottom">text</Tooltip> to see a tooltip.
</p>
<button>
Hover <Tooltip text="Button tooltip" position="top">here</Tooltip> for tooltip.
</button>
</div>
);
};
export default App;
Šis piemērs parāda, kā izmantot Tooltip komponentu, lai pievienotu rīka padomus tekstam un pogām. Jūs varat pielāgot rīka padoma tekstu un pozīciju, izmantojot text un position props.
4. Rīka padoma stilizēšana
Pievienojiet CSS stilus, lai pozicionētu un stilizētu rīka padomu. Šeit ir vienkāršs piemērs:
.tooltip {
position: absolute;
background-color: rgba(0, 0, 0, 0.8); /* Dark background */
color: white;
padding: 5px;
border-radius: 3px;
font-size: 12px;
z-index: 1000; /* Ensure it's on top of other content */
white-space: pre-line; /* Respect line breaks in the text prop */
}
CSS paskaidrojums:
position: absolute: Pozicionē rīka padomu attiecībā prettooltip-root. FunkcijaupdatePositionReact komponentā aprēķina precīzastopunleftvērtības, lai pozicionētu rīka padomu tuvu izsaucējelementam.background-color: rgba(0, 0, 0, 0.8): Izveido nedaudz caurspīdīgu, tumšu fonu rīka padomam.white-space: pre-line: Tas ir svarīgi, lai saglabātu rindiņu pārtraukumus, ko jūs varat iekļauttextprops. Bez šī rīka padoma teksts parādītos vienā rindā.
Globāli apsvērumi un labākā prakse
Izstrādājot React lietotnes globālai auditorijai, apsveriet šīs labākās prakses:
- Internacionalizācija (i18n): Izmantojiet bibliotēku, piemēram,
react-i18nextvaiFormatJS, lai apstrādātu tulkojumus un lokalizāciju. Tas ļauj jums viegli pielāgot savu lietotni dažādām valodām un reģioniem. Modālajiem logiem un rīka padomiem nodrošiniet, ka teksta saturs ir pareizi iztulkots. - No labās uz kreiso pusi (RTL) atbalsts: Valodām, kas tiek lasītas no labās uz kreiso pusi (piemēram, arābu, ebreju), nodrošiniet, ka jūsu modālie logi un rīka padomi tiek parādīti pareizi. Jums var nākties pielāgot elementu pozicionēšanu un stilu, lai pielāgotos RTL izkārtojumiem. CSS loģiskās īpašības (piemēram,
margin-inline-start, nevismargin-left) var būt noderīgas. - Kultūras jutīgums: Esiet uzmanīgi pret kultūras atšķirībām, veidojot savus modālos logus un rīka padomus. Izvairieties no attēlu vai simbolu izmantošanas, kas noteiktās kultūrās varētu būt aizskaroši vai nepiemēroti.
- Laika joslas un datumu formāti: Ja jūsu modālie logi vai rīka padomi attēlo datumus vai laikus, nodrošiniet, ka tie ir formatēti atbilstoši lietotāja lokalizācijai un laika joslai. Ar to var palīdzēt tādas bibliotēkas kā
moment.js(lai arī novecojusi, joprojām plaši izmantota) vaidate-fns. - Pieejamība dažādām spējām: Ievērojiet pieejamības vadlīnijas (WCAG), lai nodrošinātu, ka jūsu modālie logi un rīka padomi ir lietojami cilvēkiem ar invaliditāti. Tas ietver alternatīva teksta nodrošināšanu attēliem, pietiekama krāsu kontrasta nodrošināšanu un tastatūras navigācijas atbalstu.
Noslēgums
React portāli ir spēcīgs rīks elastīgu un pieejamu lietotāja saskarņu veidošanai. Izprotot, kā tos efektīvi izmantot, jūs varat izveidot modālos logus un rīka padomus, kas uzlabo lietotāja pieredzi un uzlabo jūsu React lietotņu struktūru un uzturēšanu. Atcerieties piešķirt prioritāti pieejamībai un globāliem apsvērumiem, izstrādājot lietotnes daudzveidīgai auditorijai, nodrošinot, ka jūsu lietotnes ir iekļaujošas un lietojamas visiem.