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/sv/3-terrarium/3-intro-to-DOM-and-closures
leestott 425e0f6fbe
🌐 Update translations via Co-op Translator
3 weeks ago
..
README.md 🌐 Update translations via Co-op Translator 3 weeks ago
assignment.md 🌐 Update translations via Co-op Translator 4 weeks ago

README.md

Terrariumprojekt Del 3: DOM-manipulation och en Slutning

DOM och en slutning

Sketchnote av Tomomi Imura

Förhandsquiz

Förhandsquiz

Introduktion

Att manipulera DOM, eller "Document Object Model", är en central del av webbutveckling. Enligt MDN är "Document Object Model (DOM) den datarepresentation av objekten som utgör strukturen och innehållet i ett dokument på webben." Utmaningarna med att manipulera DOM har ofta varit anledningen till att använda JavaScript-ramverk istället för ren JavaScript för att hantera DOM, men vi kommer att klara oss själva!

Dessutom kommer denna lektion att introducera idén om en JavaScript-slutning, som du kan tänka på som en funktion innesluten av en annan funktion så att den inre funktionen har tillgång till den yttre funktionens scope.

JavaScript-slutningar är ett omfattande och komplext ämne. Denna lektion berör den mest grundläggande idén att i denna terrariums kod kommer du att hitta en slutning: en inre funktion och en yttre funktion konstruerade på ett sätt som tillåter den inre funktionen att få tillgång till den yttre funktionens scope. För mycket mer information om hur detta fungerar, besök den omfattande dokumentationen.

Vi kommer att använda en slutning för att manipulera DOM.

Tänk på DOM som ett träd som representerar alla sätt som ett webbdokument kan manipuleras. Olika API:er (Application Program Interfaces) har skrivits så att programmerare, med hjälp av sitt valda programmeringsspråk, kan komma åt DOM och redigera, ändra, omorganisera och på andra sätt hantera det.

DOM-trädrepresentation

En representation av DOM och HTML-markupen som refererar till det. Från Olfa Nasraoui

I denna lektion kommer vi att slutföra vårt interaktiva terrariumprojekt genom att skapa JavaScript som gör det möjligt för en användare att manipulera växterna på sidan.

Förkunskaper

Du bör ha HTML och CSS för ditt terrarium färdigbyggt. Vid slutet av denna lektion kommer du att kunna flytta växterna in och ut ur terrariet genom att dra dem.

Uppgift

I din terrarium-mapp, skapa en ny fil som heter script.js. Importera den filen i <head>-sektionen:

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

Notera: använd defer när du importerar en extern JavaScript-fil i HTML-filen för att låta JavaScript exekveras först efter att HTML-filen har laddats helt. Du kan också använda attributet async, vilket tillåter att skriptet exekveras medan HTML-filen parsas, men i vårt fall är det viktigt att HTML-elementen är fullt tillgängliga för dragning innan vi låter drag-skriptet exekveras.


DOM-elementen

Det första du behöver göra är att skapa referenser till de element som du vill manipulera i DOM. I vårt fall är det de 14 växterna som för närvarande väntar i sidofälten.

Uppgift

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'));

Vad händer här? Du refererar till dokumentet och letar igenom dess DOM för att hitta ett element med ett specifikt Id. Kom ihåg att du i den första lektionen om HTML gav individuella Id:n till varje växtbild (id="plant1")? Nu kommer du att dra nytta av det arbetet. Efter att ha identifierat varje element skickar du det objektet till en funktion som heter dragElement som du snart kommer att bygga. På så sätt blir elementet i HTML nu dragbart, eller kommer att bli det snart.

Varför refererar vi till element med Id? Varför inte med deras CSS-klass? Du kan hänvisa till den tidigare lektionen om CSS för att svara på denna fråga.


Slutningen

Nu är du redo att skapa slutningen dragElement, som är en yttre funktion som innesluter en inre funktion eller funktioner (i vårt fall kommer vi att ha tre).

Slutningar är användbara när en eller flera funktioner behöver tillgång till en yttre funktions scope. Här är ett exempel:

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

I detta exempel omger funktionen displayCandy en funktion som lägger till en ny godistyp i en array som redan existerar i funktionen. Om du skulle köra denna kod skulle arrayen candy vara odefinierad, eftersom den är en lokal variabel (lokal för slutningen).

Hur kan du göra arrayen candy tillgänglig? Försök att flytta den utanför slutningen. På så sätt blir arrayen global istället för att bara vara tillgänglig inom slutningens lokala scope.

Uppgift

Under elementdeklarationerna i script.js, skapa en funktion:

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

dragElement får sitt terrariumElement-objekt från deklarationerna högst upp i skriptet. Sedan sätter du några lokala positioner till 0 för objektet som skickas in i funktionen. Dessa är de lokala variabler som kommer att manipuleras för varje element när du lägger till drag-och-släpp-funktionalitet inom slutningen för varje element. Terrariet kommer att fyllas med dessa dragna element, så applikationen behöver hålla reda på var de placeras.

Dessutom tilldelas terrariumElement som skickas till denna funktion en pointerdown-händelse, som är en del av webb-API:er designade för att hjälpa till med DOM-hantering. onpointerdown triggas när en knapp trycks ner, eller i vårt fall, när ett dragbart element berörs. Denna händelsehanterare fungerar på både webb- och mobilwebbläsare, med några få undantag.

Händelsehanteraren onclick har mycket mer stöd över olika webbläsare; varför skulle du inte använda den här? Fundera på vilken exakt typ av skärminteraktion du försöker skapa här.


Pointerdrag-funktionen

terrariumElement är redo att dras runt; när händelsen onpointerdown triggas, anropas funktionen pointerDrag. Lägg till den funktionen precis under denna rad: terrariumElement.onpointerdown = pointerDrag;:

Uppgift

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

Flera saker händer. Först förhindrar du de standardhändelser som normalt inträffar vid pointerdown genom att använda e.preventDefault();. På så sätt har du mer kontroll över gränssnittets beteende.

Återkom till denna rad när du har byggt klart skriptfilen och testa utan e.preventDefault() - vad händer?

För det andra, öppna index.html i ett webbläsarfönster och inspektera gränssnittet. När du klickar på en växt kan du se hur händelsen 'e' fångas. Gräv i händelsen för att se hur mycket information som samlas in av en enda pointerdown-händelse!

Nästa steg är att notera hur de lokala variablerna pos3 och pos4 sätts till e.clientX. Du kan hitta värdena för e i inspektionspanelen. Dessa värden fångar x- och y-koordinaterna för växten i det ögonblick du klickar på eller rör vid den. Du kommer att behöva finjusterad kontroll över växternas beteende när du klickar och drar dem, så du håller reda på deras koordinater.

Börjar det bli tydligare varför hela denna app är byggd med en stor slutning? Om den inte var det, hur skulle du då kunna hålla scope för var och en av de 14 dragbara växterna?

Slutför den inledande funktionen genom att lägga till två fler pekarhändelsemanipulationer under pos4 = e.clientY:

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

Nu anger du att du vill att växten ska dras med pekaren när du flyttar den, och att draggesten ska sluta när du avmarkerar växten. onpointermove och onpointerup är alla delar av samma API som onpointerdown. Gränssnittet kommer nu att kasta fel eftersom du ännu inte har definierat funktionerna elementDrag och stopElementDrag, så bygg ut dem härnäst.

Funktionerna elementDrag och stopElementDrag

Du kommer att slutföra din slutning genom att lägga till två fler interna funktioner som hanterar vad som händer när du drar en växt och slutar dra den. Det beteende du vill ha är att du kan dra vilken växt som helst när som helst och placera den var som helst på skärmen. Detta gränssnitt är ganska flexibelt (det finns till exempel ingen dropzon) för att låta dig designa ditt terrarium precis som du vill genom att lägga till, ta bort och omplacera växter.

Uppgift

Lägg till funktionen elementDrag precis efter den avslutande måsvingeparentesen för 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';
}

I denna funktion gör du många justeringar av de initiala positionerna 1-4 som du satte som lokala variabler i den yttre funktionen. Vad händer här?

När du drar omfördelar du pos1 genom att göra den lika med pos3 (som du tidigare satte som e.clientX) minus det aktuella värdet för e.clientX. Du gör en liknande operation för pos2. Sedan återställer du pos3 och pos4 till de nya X- och Y-koordinaterna för elementet. Du kan se dessa förändringar i konsolen när du drar. Sedan manipulerar du växtens CSS-stil för att ställa in dess nya position baserat på de nya positionerna för pos1 och pos2, och beräknar växtens topp- och vänsterkoordinater baserat på jämförelsen av dess offset med dessa nya positioner.

offsetTop och offsetLeft är CSS-egenskaper som ställer in ett elements position baserat på dess förälder; dess förälder kan vara vilket element som helst som inte är positionerat som static.

Alla dessa omräkningar av positioner gör att du kan finjustera terrariets och växternas beteende.

Uppgift

Den sista uppgiften för att slutföra gränssnittet är att lägga till funktionen stopElementDrag efter den avslutande måsvingeparentesen för elementDrag:

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

Denna lilla funktion återställer händelserna onpointerup och onpointermove så att du antingen kan starta om växtens rörelse genom att börja dra den igen, eller börja dra en ny växt.

Vad händer om du inte sätter dessa händelser till null?

Nu har du slutfört ditt projekt!

🥇Grattis! Du har färdigställt ditt vackra terrarium. färdigt terrarium


🚀Utmaning

Lägg till en ny händelsehanterare i din slutning för att göra något mer med växterna; till exempel, dubbelklicka på en växt för att flytta den längst fram. Var kreativ!

Efterhandsquiz

Efterhandsquiz

Granskning & Självstudier

Även om det verkar trivialt att dra element runt på skärmen finns det många sätt att göra detta och många fallgropar, beroende på vilken effekt du vill uppnå. Faktum är att det finns ett helt drag-och-släpp-API som du kan prova. Vi använde det inte i denna modul eftersom effekten vi ville ha var något annorlunda, men prova detta API på ditt eget projekt och se vad du kan åstadkomma.

Hitta mer information om pekarhändelser i W3C-dokumentationen och på MDN webbdokumentation.

Kontrollera alltid webbläsarkapabiliteter med CanIUse.com.

Uppgift

Arbeta lite mer med DOM


Ansvarsfriskrivning:
Detta dokument har översatts med hjälp av AI-översättningstjänsten Co-op Translator. Även om vi strävar efter noggrannhet, vänligen notera att automatiska översättningar kan innehålla fel eller felaktigheter. Det ursprungliga dokumentet på dess originalspråk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning.