You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/ro/3-terrarium/3-intro-to-DOM-and-closures/README.md

15 KiB

Proiect Terrarium Partea 3: Manipularea DOM-ului și o Închidere

DOM și o închidere

Sketchnote de Tomomi Imura

Chestionar Pre-Lecție

Chestionar pre-lecție

Introducere

Manipularea DOM-ului, sau "Modelul Obiectului Document", este un aspect esențial al dezvoltării web. Conform MDN, "Modelul Obiectului Document (DOM) este reprezentarea datelor obiectelor care alcătuiesc structura și conținutul unui document pe web." Provocările legate de manipularea DOM-ului pe web au fost adesea motivul utilizării framework-urilor JavaScript în locul JavaScript-ului simplu pentru gestionarea DOM-ului, dar ne vom descurca pe cont propriu!

În plus, această lecție va introduce ideea unei închideri JavaScript, pe care o puteți considera ca o funcție închisă de o altă funcție, astfel încât funcția interioară are acces la domeniul funcției exterioare.

Închiderile JavaScript sunt un subiect vast și complex. Această lecție abordează cea mai simplă idee: în codul acestui terrarium, veți găsi o închidere: o funcție interioară și o funcție exterioară construite astfel încât funcția interioară să aibă acces la domeniul funcției exterioare. Pentru mult mai multe informații despre cum funcționează acest lucru, vă rugăm să vizitați documentația extinsă.

Vom folosi o închidere pentru a manipula DOM-ul.

Gândiți-vă la DOM ca la un arbore, care reprezintă toate modurile în care un document de pagină web poate fi manipulat. Diverse API-uri (Interfețe de Programare a Aplicațiilor) au fost scrise astfel încât programatorii, folosind limbajul de programare preferat, să poată accesa DOM-ul și să-l editeze, schimbe, rearanjeze și să-l gestioneze în alte moduri.

Reprezentarea arborelui DOM

O reprezentare a DOM-ului și a marcajului HTML care îl referențiază. De la Olfa Nasraoui

În această lecție, vom finaliza proiectul nostru interactiv de terrarium prin crearea JavaScript-ului care va permite utilizatorului să manipuleze plantele de pe pagină.

Prerechizite

Ar trebui să aveți HTML-ul și CSS-ul pentru terrarium-ul vostru construite. Până la sfârșitul acestei lecții, veți putea muta plantele în și din terrarium prin tragerea lor.

Sarcină

În folderul terrarium, creați un fișier nou numit script.js. Importați acel fișier în secțiunea <head>:

	<script src="./script.js" defer></script>

Notă: folosiți defer atunci când importați un fișier JavaScript extern în fișierul HTML pentru a permite executarea JavaScript-ului doar după ce fișierul HTML a fost complet încărcat. De asemenea, puteți folosi atributul async, care permite scriptului să se execute în timp ce fișierul HTML este analizat, dar în cazul nostru, este important să avem elementele HTML complet disponibile pentru tragere înainte de a permite executarea scriptului de tragere.


Elementele DOM

Primul lucru pe care trebuie să-l faceți este să creați referințe la elementele pe care doriți să le manipulați în DOM. În cazul nostru, acestea sunt cele 14 plante care așteaptă în barele laterale.

Sarcină

dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
dragElement(document.getElementById('plant4'));
dragElement(document.getElementById('plant5'));
dragElement(document.getElementById('plant6'));
dragElement(document.getElementById('plant7'));
dragElement(document.getElementById('plant8'));
dragElement(document.getElementById('plant9'));
dragElement(document.getElementById('plant10'));
dragElement(document.getElementById('plant11'));
dragElement(document.getElementById('plant12'));
dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));

Ce se întâmplă aici? Referențiați documentul și căutați în DOM-ul său pentru a găsi un element cu un anumit Id. Amintiți-vă că în prima lecție despre HTML ați dat Id-uri individuale fiecărei imagini de plantă (id="plant1")? Acum veți folosi acel efort. După identificarea fiecărui element, transmiteți acel element unei funcții numite dragElement pe care o veți construi în curând. Astfel, elementul din HTML este acum activat pentru tragere, sau va fi în curând.

De ce referențiem elementele prin Id? De ce nu prin clasa CSS? Puteți consulta lecția anterioară despre CSS pentru a răspunde la această întrebare.


Închiderea

Acum sunteți gata să creați închiderea dragElement, care este o funcție exterioară ce închide o funcție sau funcții interioare (în cazul nostru, vom avea trei).

Închiderile sunt utile atunci când una sau mai multe funcții trebuie să acceseze domeniul funcției exterioare. Iată un exemplu:

function displayCandy(){
	let candy = ['jellybeans'];
	function addCandy(candyType) {
		candy.push(candyType)
	}
	addCandy('gumdrops');
}
displayCandy();
console.log(candy)

În acest exemplu, funcția displayCandy înconjoară o funcție care adaugă un nou tip de bomboană într-un array care există deja în funcție. Dacă ați rula acest cod, array-ul candy ar fi nedefinit, deoarece este o variabilă locală (locală pentru închidere).

Cum puteți face array-ul candy accesibil? Încercați să-l mutați în afara închiderii. În acest fel, array-ul devine global, în loc să rămână disponibil doar pentru domeniul local al închiderii.

Sarcină

Sub declarațiile elementelor din script.js, creați o funcție:

function dragElement(terrariumElement) {
	//set 4 positions for positioning on the screen
	let pos1 = 0,
		pos2 = 0,
		pos3 = 0,
		pos4 = 0;
	terrariumElement.onpointerdown = pointerDrag;
}

dragElement primește obiectul său terrariumElement din declarațiile de la începutul scriptului. Apoi, setați câteva poziții locale la 0 pentru obiectul transmis funcției. Acestea sunt variabilele locale care vor fi manipulate pentru fiecare element pe măsură ce adăugați funcționalitatea de tragere și plasare în închidere pentru fiecare element. Terrarium-ul va fi populat de aceste elemente trase, astfel încât aplicația trebuie să țină evidența locului unde sunt plasate.

În plus, elementul terrariumElement transmis acestei funcții este atribuit unui eveniment pointerdown, care face parte din web APIs concepute pentru a ajuta la gestionarea DOM-ului. onpointerdown se declanșează atunci când un buton este apăsat sau, în cazul nostru, un element care poate fi tras este atins. Acest handler de evenimente funcționează atât pe navigatoare web cât și mobile, cu câteva excepții.

Handler-ul de evenimente onclick are mult mai mult suport cross-browser; de ce nu l-ați folosi aici? Gândiți-vă la tipul exact de interacțiune pe ecran pe care încercați să o creați aici.


Funcția Pointerdrag

Elementul terrariumElement este gata să fie tras; când evenimentul onpointerdown este declanșat, funcția pointerDrag este invocată. Adăugați acea funcție chiar sub această linie: terrariumElement.onpointerdown = pointerDrag;:

Sarcină

function pointerDrag(e) {
	e.preventDefault();
	console.log(e);
	pos3 = e.clientX;
	pos4 = e.clientY;
}

Se întâmplă mai multe lucruri. În primul rând, preveniți evenimentele implicite care se întâmplă în mod normal la pointerdown să aibă loc folosind e.preventDefault();. În acest fel aveți mai mult control asupra comportamentului interfeței.

Reveniți la această linie după ce ați construit complet fișierul script și încercați fără e.preventDefault() - ce se întâmplă?

În al doilea rând, deschideți index.html într-o fereastră de browser și inspectați interfața. Când faceți clic pe o plantă, puteți vedea cum evenimentul 'e' este capturat. Explorați evenimentul pentru a vedea cât de multe informații sunt colectate de un singur eveniment pointer down!

Apoi, observați cum variabilele locale pos3 și pos4 sunt setate la e.clientX. Puteți găsi valorile e în panoul de inspecție. Aceste valori capturează coordonatele x și y ale plantei în momentul în care faceți clic pe ea sau o atingeți. Veți avea nevoie de control detaliat asupra comportamentului plantelor pe măsură ce le faceți clic și le trageți, astfel încât să țineți evidența coordonatelor lor.

Devine mai clar de ce această aplicație este construită cu o închidere mare? Dacă nu ar fi, cum ați menține domeniul pentru fiecare dintre cele 14 plante care pot fi trase?

Completați funcția inițială adăugând două manipulări suplimentare ale evenimentelor pointer sub pos4 = e.clientY:

document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;

Acum indicați că doriți ca planta să fie trasă împreună cu pointerul pe măsură ce o mutați și ca gestul de tragere să se oprească atunci când deselectați planta. onpointermove și onpointerup fac parte din același API ca onpointerdown. Interfața va arunca erori acum, deoarece nu ați definit încă funcțiile elementDrag și stopElementDrag, așa că construiți-le în continuare.

Funcțiile elementDrag și stopElementDrag

Veți completa închiderea adăugând două funcții interne suplimentare care vor gestiona ce se întâmplă atunci când trageți o plantă și opriți tragerea ei. Comportamentul dorit este ca să puteți trage orice plantă în orice moment și să o plasați oriunde pe ecran. Această interfață este destul de neimpusă (nu există o zonă de plasare, de exemplu) pentru a vă permite să proiectați terrarium-ul exact așa cum doriți, adăugând, eliminând și repoziționând plantele.

Sarcină

Adăugați funcția elementDrag imediat după acolada de închidere a pointerDrag:

function elementDrag(e) {
	pos1 = pos3 - e.clientX;
	pos2 = pos4 - e.clientY;
	pos3 = e.clientX;
	pos4 = e.clientY;
	console.log(pos1, pos2, pos3, pos4);
	terrariumElement.style.top = terrariumElement.offsetTop - pos2 + 'px';
	terrariumElement.style.left = terrariumElement.offsetLeft - pos1 + 'px';
}

În această funcție, faceți multe modificări ale pozițiilor inițiale 1-4 pe care le-ați setat ca variabile locale în funcția exterioară. Ce se întâmplă aici?

Pe măsură ce trageți, reasignați pos1 făcându-l egal cu pos3 (pe care l-ați setat anterior ca e.clientX) minus valoarea curentă e.clientX. Faceți o operație similară pentru pos2. Apoi, resetați pos3 și pos4 la noile coordonate X și Y ale elementului. Puteți urmări aceste modificări în consolă pe măsură ce trageți. Apoi, manipulați stilul css al plantei pentru a seta poziția sa nouă pe baza noilor poziții ale pos1 și pos2, calculând coordonatele X și Y ale plantei pe baza comparării offset-ului său cu aceste poziții noi.

offsetTop și offsetLeft sunt proprietăți CSS care setează poziția unui element pe baza poziției părintelui său; părintele său poate fi orice element care nu este poziționat ca static.

Toate aceste recalculări ale poziționării vă permit să ajustați fin comportamentul terrarium-ului și al plantelor sale.

Sarcină

Ultima sarcină pentru a finaliza interfața este să adăugați funcția stopElementDrag după acolada de închidere a elementDrag:

function stopElementDrag() {
	document.onpointerup = null;
	document.onpointermove = null;
}

Această funcție mică resetează evenimentele onpointerup și onpointermove astfel încât să puteți relua progresul plantei voastre începând să o trageți din nou sau să începeți să trageți o plantă nouă.

Ce se întâmplă dacă nu setați aceste evenimente la null?

Acum ați finalizat proiectul vostru!

🥇Felicitări! Ați terminat terrarium-ul vostru frumos! terrarium finalizat


🚀Provocare

Adăugați un nou handler de evenimente în închiderea voastră pentru a face ceva suplimentar cu plantele; de exemplu, faceți dublu clic pe o plantă pentru a o aduce în față. Fiți creativi!

Chestionar Post-Lecție

Chestionar post-lecție

Recapitulare și Studiu Individual

Deși tragerea elementelor pe ecran pare trivială, există multe moduri de a face acest lucru și multe capcane, în funcție de efectul pe care îl căutați. De fapt, există un întreg API de tragere și plasare pe care îl puteți încerca. Nu l-am folosit în acest modul deoarece efectul dorit era oarecum diferit, dar încercați acest API pe propriul proiect și vedeți ce puteți realiza.

Găsiți mai multe informații despre evenimentele pointer pe documentația W3C și pe documentația web MDN.

Verificați întotdeauna capacitățile browserului folosind CanIUse.com.

Temă

Lucrați puțin mai mult cu DOM-ul


Declinare de responsabilitate:
Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. Deși ne străduim să asigurăm acuratețea, vă rugăm să rețineți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa natală ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm responsabilitatea pentru eventualele neînțelegeri sau interpretări greșite care pot apărea din utilizarea acestei traduceri.