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/fi/3-terrarium/3-intro-to-DOM-and-closures/README.md

14 KiB

Terrarium-projekti Osa 3: DOM-manipulointi ja sulkeuma

DOM ja sulkeuma

Sketchnote: Tomomi Imura

Ennakkokysely

Ennakkokysely

Johdanto

DOM-manipulointi eli "Document Object Model" on keskeinen osa verkkosivujen kehittämistä. MDN:n mukaan "Document Object Model (DOM) on verkkosivun rakenteen ja sisällön muodostavien objektien tietoesitys." DOM-manipuloinnin haasteet ovat usein johtaneet siihen, että JavaScript-kehyksiä käytetään sen hallintaan sen sijaan, että käytettäisiin pelkkää JavaScriptiä. Tässä projektissa pärjäämme kuitenkin ilman kehyksiä!

Lisäksi tässä oppitunnissa esitellään JavaScript-sulkeuma, jonka voi ajatella olevan funktio, joka on suljettu toisen funktion sisään, jolloin sisempi funktio pääsee käsiksi ulomman funktion laajuuteen.

JavaScript-sulkeumat ovat laaja ja monimutkainen aihe. Tässä oppitunnissa käsitellään perusidea, joka liittyy terrariumin koodiin: sulkeuma, jossa sisempi funktio ja ulompi funktio on rakennettu siten, että sisempi funktio pääsee käsiksi ulomman funktion laajuuteen. Lisätietoja aiheesta löytyy laajasta dokumentaatiosta.

Käytämme sulkeumaa DOM-manipulointiin.

Ajattele DOM:ia puuna, joka edustaa kaikkia tapoja, joilla verkkosivun dokumenttia voidaan manipuloida. Erilaisia API:ita (Application Program Interfaces) on kirjoitettu, jotta ohjelmoijat voivat käyttää DOM:ia ja muokata, järjestellä ja hallita sitä haluamallaan tavalla.

DOM-puun esitys

DOM:n ja siihen viittaavan HTML-merkinnän esitys. Lähde: Olfa Nasraoui

Tässä oppitunnissa viimeistelemme interaktiivisen terrarium-projektimme luomalla JavaScriptin, joka mahdollistaa kasvien siirtämisen sivulla.

Esitietovaatimukset

Sinulla tulisi olla terrariumin HTML ja CSS valmiina. Oppitunnin lopussa pystyt siirtämään kasveja terrariumiin ja sieltä pois vetämällä niitä.

Tehtävä

Luo terrarium-kansioon uusi tiedosto nimeltä script.js. Tuo tämä tiedosto <head>-osioon:

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

Huom: käytä defer-attribuuttia tuodessasi ulkoisen JavaScript-tiedoston HTML-tiedostoon, jotta JavaScript suoritetaan vasta, kun HTML-tiedosto on ladattu kokonaan. Voisit myös käyttää async-attribuuttia, joka sallii skriptin suorittamisen HTML-tiedoston jäsentämisen aikana, mutta tässä tapauksessa on tärkeää, että HTML-elementit ovat täysin saatavilla ennen kuin vetämistoiminto suoritetaan.


DOM-elementit

Ensimmäinen tehtäväsi on luoda viittaukset DOM:ssa oleviin elementteihin, joita haluat manipuloida. Meidän tapauksessamme nämä ovat 14 kasvia, jotka odottavat sivupalkissa.

Tehtävä

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

Mitä tässä tapahtuu? Viittaat dokumenttiin ja etsit sen DOM:sta elementin, jolla on tietty Id. Muistatko ensimmäisestä HTML-oppitunnista, että annoit yksilölliset Id:t jokaiselle kasvikuvalle (id="plant1")? Nyt hyödynnät tätä työtä. Kun olet tunnistanut jokaisen elementin, välität sen funktiolle nimeltä dragElement, jonka rakennat hetken kuluttua. Näin HTML-elementti on nyt vedettävissä, tai tulee olemaan pian.

Miksi viittaamme elementteihin Id:n avulla? Miksi emme CSS-luokan avulla? Voit palata edelliseen CSS-oppituntiin vastataksesi tähän kysymykseen.


Sulkeuma

Nyt olet valmis luomaan dragElement-sulkeuman, joka on ulompi funktio, joka sulkee sisemmän funktion tai funktiot (meidän tapauksessamme niitä on kolme).

Sulkeumat ovat hyödyllisiä, kun yksi tai useampi funktio tarvitsee pääsyn ulomman funktion laajuuteen. Tässä esimerkki:

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

Tässä esimerkissä displayCandy-funktio ympäröi funktion, joka lisää uuden karkkityypin jo olemassa olevaan taulukkoon. Jos suorittaisit tämän koodin, candy-taulukko olisi määrittelemätön, koska se on paikallinen muuttuja (paikallinen sulkeumalle).

Kuinka voit tehdä candy-taulukon saatavilla? Kokeile siirtää se sulkeuman ulkopuolelle. Näin taulukosta tulee globaali, eikä se jää vain sulkeuman paikalliseen laajuuteen.

Tehtävä

Luo script.js-tiedoston elementtien määrittelyjen alle funktio:

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

dragElement saa terrariumElement-objektinsa skriptin yläosassa tehdyistä määrittelyistä. Sitten asetat joitakin paikallisia sijainteja 0:ksi funktiolle välitetylle objektille. Nämä ovat paikallisia muuttujia, joita manipuloidaan jokaiselle elementille, kun lisäät vetämis- ja pudotustoiminnallisuuden sulkeuman sisällä. Terrarium täytetään näillä vedettävillä elementeillä, joten sovelluksen täytyy pitää kirjaa siitä, mihin ne sijoitetaan.

Lisäksi funktiolle välitetty terrariumElement-objekti saa pointerdown-tapahtuman, joka on osa web-API:ita, jotka on suunniteltu auttamaan DOM:n hallinnassa. onpointerdown laukeaa, kun painiketta painetaan, tai meidän tapauksessamme, kun vedettävää elementtiä kosketetaan. Tämä tapahtumankäsittelijä toimii sekä web- että mobiiliselaimissa, muutamia poikkeuksia lukuun ottamatta.

Tapahtumankäsittelijä onclick on paljon laajemmin tuettu eri selaimissa; miksi et käyttäisi sitä tässä? Mieti tarkasti, millaista ruudun vuorovaikutusta yrität luoda tässä.


Pointerdrag-funktio

terrariumElement on valmis vedettäväksi; kun onpointerdown-tapahtuma laukeaa, funktio pointerDrag kutsutaan. Lisää tämä funktio heti tämän rivin alle: terrariumElement.onpointerdown = pointerDrag;:

Tehtävä

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

Useita asioita tapahtuu. Ensinnäkin estät oletustapahtumat, jotka normaalisti tapahtuvat pointerdown-tapahtumassa, käyttämällä e.preventDefault();. Näin sinulla on enemmän hallintaa käyttöliittymän käyttäytymisestä.

Palaa tähän kohtaan, kun olet rakentanut skriptitiedoston kokonaan, ja kokeile ilman e.preventDefault() - mitä tapahtuu?

Toiseksi avaa index.html selaimessa ja tarkastele käyttöliittymää. Kun napsautat kasvia, näet kuinka 'e'-tapahtuma tallennetaan. Tutki tapahtumaa nähdäksesi, kuinka paljon tietoa kerätään yhdestä pointerdown-tapahtumasta!

Seuraavaksi huomaa, kuinka paikalliset muuttujat pos3 ja pos4 asetetaan arvoon e.clientX. Voit löytää e-arvot tarkastelupaneelista. Nämä arvot tallentavat kasvin x- ja y-koordinaatit sillä hetkellä, kun napsautat tai kosketat sitä. Tarvitset tarkkaa hallintaa kasvien käyttäytymisestä, kun napsautat ja vedät niitä, joten pidät kirjaa niiden koordinaateista.

Alkaako olla selvempää, miksi koko sovellus rakennetaan yhdellä suurella sulkeumalla? Jos ei olisi, kuinka ylläpitäisit laajuutta jokaiselle 14 vedettävälle kasville?

Täydennä alkuperäinen funktio lisäämällä kaksi muuta pointer-tapahtuman käsittelyä pos4 = e.clientY-rivin alle:

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

Nyt ilmoitat, että haluat kasvin liikkuvan osoittimen mukana, kun siirrät sitä, ja että vetämisliike pysähtyy, kun lopetat kasvin valinnan. onpointermove ja onpointerup ovat kaikki osa samaa API:ta kuin onpointerdown. Käyttöliittymä heittää nyt virheitä, koska et ole vielä määritellyt elementDrag- ja stopElementDrag-funktioita, joten rakenna ne seuraavaksi.

elementDrag- ja stopElementDrag-funktiot

Viimeistelet sulkeumasi lisäämällä kaksi sisäistä funktiota, jotka käsittelevät, mitä tapahtuu, kun vedät kasvia ja lopetat sen vetämisen. Haluttu käyttäytyminen on, että voit vetää mitä tahansa kasvia milloin tahansa ja sijoittaa sen mihin tahansa ruudulla. Tämä käyttöliittymä on melko joustava (esimerkiksi pudotusaluetta ei ole), jotta voit suunnitella terrariumin juuri haluamallasi tavalla lisäämällä, poistamalla ja siirtämällä kasveja.

Tehtävä

Lisää elementDrag-funktio heti pointerDrag-funktion sulkevan aaltosulkeen jälkeen:

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

Tässä funktiossa muokkaat paljon alkuperäisiä sijainteja 1-4, jotka asetettiin paikallisiksi muuttujiksi ulommassa funktiossa. Mitä tässä tapahtuu?

Kun vedät, määrität pos1:n uudelleen tekemällä siitä yhtä suuri kuin pos3 (jonka asetit aiemmin arvoksi e.clientX) miinus nykyinen e.clientX-arvo. Teet samanlaisen operaation pos2:lle. Sitten asetat pos3:n ja pos4:n uudelleen elementin uusiin x- ja y-koordinaatteihin. Voit seurata näitä muutoksia konsolissa vetämisen aikana. Sitten muokkaat kasvin css-tyyliä asettaaksesi sen uuden sijainnin perustuen uusiin pos1- ja pos2-sijainteihin, laskemalla kasvin ylä- ja vasemman x- ja y-koordinaatin sen offsetin perusteella.

offsetTop ja offsetLeft ovat CSS-ominaisuuksia, jotka asettavat elementin sijainnin sen vanhemman elementin perusteella; vanhempi elementti voi olla mikä tahansa, joka ei ole asetettu static-sijaintiin.

Kaikki tämä sijainnin uudelleenlaskenta mahdollistaa terrariumin ja sen kasvien käyttäytymisen hienosäädön.

Tehtävä

Viimeinen tehtävä käyttöliittymän viimeistelemiseksi on lisätä stopElementDrag-funktio elementDrag-funktion sulkevan aaltosulkeen jälkeen:

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

Tämä pieni funktio nollaa onpointerup- ja onpointermove-tapahtumat, jotta voit joko aloittaa kasvin siirtämisen uudelleen tai aloittaa uuden kasvin vetämisen.

Mitä tapahtuu, jos et aseta näitä tapahtumia nulliksi?

Nyt olet valmis projektiisi!

🥇Onnittelut! Olet viimeistellyt kauniin terrariumisi. valmis terrarium


🚀Haaste

Lisää uusi tapahtumankäsittelijä sulkeumaasi, jotta kasveille tapahtuisi jotain muuta; esimerkiksi kaksoisnapsauta kasvia tuodaksesi sen etualalle. Ole luova!

Jälkikysely

Jälkikysely

Kertaus ja itseopiskelu

Vaikka elementtien vetäminen ruudulla vaikuttaa yksinkertaiselta, on olemassa monia tapoja tehdä tämä ja monia sudenkuoppia riippuen halutusta efektistä. Itse asiassa on olemassa kokonainen drag and drop API, jota voit kokeilla. Emme käyttäneet sitä tässä moduulissa, koska haluamamme efekti oli hieman erilainen, mutta kokeile tätä API:a omassa projektissasi ja katso, mitä saat aikaan.

Lisätietoja pointer-tapahtumista löytyy W3C-dokumenteista ja MDN-web-dokumenteista.

Tarkista aina selainten yhteensopivuus CanIUse.com-sivustolla.

Tehtävä

Työskentele hieman lisää DOM:n kanssa


Vastuuvapauslauseke:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua Co-op Translator. Pyrimme tarkkuuteen, mutta huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäistä asiakirjaa sen alkuperäisellä kielellä tulee pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskääntämistä. Emme ole vastuussa tämän käännöksen käytöstä aiheutuvista väärinkäsityksistä tai virhetulkinnoista.