Javascript en de DOM les 2

Hallo en welkom terug in de serie "JavaScript en de DOM". De laatste keer hebben we een aantal JavaScript-basisbegrippen behandeld en hebben we verschillende aspecten van het documentobjectmodel besproken, waaronder hoe toegang te krijgen tot knooppunten en door de DOM te navigeren. Vandaag bespreken we hoe elementen binnen het DOM kunnen worden gemanipuleerd en bespreken we het browsergebeurtenismodel.

Elementen manipuleren

In de laatste les hebben we de stappen besproken die nodig zijn om toegang te krijgen tot een verzameling DOM-knooppunten of een enkelvoudig DOM-knooppunt. De echte magie treedt op wanneer je bepaalde eigenschappen manipuleert die resulteren in wat algemeen bekend staat als "gedrag".

Elke afzonderlijke DOM-knoop heeft een verzameling eigenschappen; de meeste van deze eigenschappen bieden abstracties voor bepaalde functionaliteit. Als u bijvoorbeeld een alineanummer hebt met een ID van 'intro', kunt u de kleur van dat element vrij gemakkelijk wijzigen via de DOM API:

 document.getElementById ('intro'). style.color = '# FF0000';

Om het object / eigenschap-karakter van deze API te illustreren, is het misschien gemakkelijker om te begrijpen of we het opsplitsen door elk object aan een variabele toe te wijzen:

 var myDocument = document; var myIntro = myDocument.getElementById ('intro'); var myIntroStyles = myIntro.style; // En nu kunnen we de kleur instellen: myIntroStyles.color = '# FF0000';

Nu we een verwijzing hebben naar het 'stijl'-object van de alinea, kunnen we andere CSS-stijlen toevoegen:

 myIntroStyles.padding = '2px 3px 0 3px'; myIntroStyles.backgroundColor = '#FFF'; myIntroStyles.marginTop = '20px';

We gebruiken hier alleen de standaard CSS-eigenschappen. Het enige verschil is dat waar je normaal gesproken een streepje ('-') zou vinden, de tekst kamelen bevatte. Dus in plaats van 'margin-top' gebruiken we 'marginTop'. Het volgende, bijvoorbeeld, zou het niet werk en zou een syntaxisfout opleveren:

 myIntroStyles.padding-top = '10em'; // Produceert een syntaxisfout: // - Het teken '-' is de min-operator in JavaScript. // - Bovendien is er geen eigenschapnaam.

Eigenschappen kunnen op een array-achtige manier worden benaderd. Met deze kennis kunnen we dus een kleine functie creëren om elke stijl van een bepaald element te veranderen:

 functie changeStyle (elem, property, val) elem.style [property] = val; // Let op de vierkante haken die gebruikt worden om toegang te krijgen tot de eigenschap // U zou de bovenstaande plug-in als volgt gebruiken: var myIntro = document.getElementById ('intro'); // Grab Intro paragraph changeStyle (myIntro, 'color', 'red');

Dit is slechts een voorbeeld - om eerlijk te zijn is het waarschijnlijk geen erg nuttige functie, omdat het syntactisch sneller is om de conventionele middelen te gebruiken die eerder werden getoond (bijv.. elem.style.color = 'rood').

Naast de eigenschap 'style' zijn er nog veel meer die u kunt gebruiken om bepaalde aspecten van een knooppunt / element te manipuleren. Als u Firebug hebt geïnstalleerd, moet u in feite proberen "een element te inspecteren" en vervolgens op het tabblad "DOM" (normaal rechts of onder het elementweergavevenster) klikken om alle eigenschappen ervan te bekijken:


Eigenschappen van DOM-elementen in Firebug

Alle eigenschappen kunnen worden benaderd met behulp van de conventionele puntnotatie (bijvoorbeeld Element.tabIndex). Niet alle eigenschappen zijn primitieve gegevenstypen (strings, getallen, Booleans, etc.); de 'stijl'-eigenschap bijvoorbeeld, die we eerder hebben besproken, is een object dat zijn eigen eigenschappen bevat. Veel van de eigenschappen van een element zijn alleen leesbaar; wat ik hiermee bedoel is dat je hun waarde niet kunt veranderen. U kunt bijvoorbeeld de eigenschap 'parentNode' van een knooppunt niet rechtstreeks wijzigen. De browser genereert meestal een foutmelding als u een van deze alleen-lezen-eigenschappen probeert te wijzigen: b. FOUT: "een eigenschap instellen die alleen een getter heeft". Het is gewoon iets om op te letten ...

Een algemene vereiste is om de inhoud binnen een element te wijzigen. Er zijn een paar verschillende manieren om dit te doen. Verreweg de gemakkelijkste manier is om de eigenschap 'innerHTML' te gebruiken, zoals deze:

 var myIntro = document.getElementById ('intro'); // De huidige inhoud vervangen door nieuwe inhoud: myIntro.innerHTML = 'Nieuwe inhoud voor de verbazingwekkend paragraaf! '; // Toevoegen aan huidige inhoud: myIntro.innerHTML + = '... wat meer inhoud ...';

Het enige probleem met deze methode is dat deze niet in een standaard is gespecificeerd en niet in de DOM-specificatie. Als je daar geen last van hebt, ga je gang en gebruik je het. Het is sowieso veel sneller dan conventionele DOM-methoden, die we hierna zullen bespreken.

knooppunten

Bij het maken van inhoud via de DOM API moet u op de hoogte zijn van twee verschillende soorten knooppunten, een elementknooppunt en een tekstknooppunt. Er zijn veel andere soorten knooppunten, maar deze twee zijn voorlopig de enige belangrijke.

Als u een element wilt maken, gebruikt u de methode createElement en om een ​​tekstknooppunt te maken gebruikt u de methode createTextNode. Beide worden hieronder weergegeven:

 var myIntro = document.getElementById ('intro'); // We willen wat inhoud toevoegen aan de alinea: var someText = 'Dit is de tekst die ik wil toevoegen'; var textNode = document.createTextNode (someText); myIntro.appendChild (textNode);

Hier gebruiken we de 'appendChild'-methode om ons nieuwe tekstknooppunt aan de alinea toe te voegen. Doen op deze manier duurt iets langer dan de niet-standaard innerHTML-methode, maar het is nog steeds belangrijk om beide manieren te kennen, zodat je de juiste beslissing kunt nemen. Hier is een meer geavanceerd voorbeeld met behulp van DOM-methoden:

 var myIntro = document.getElementById ('intro'); // We willen een nieuw anker toevoegen aan de alinea: // Eerst maken we het nieuwe ankerelement: var myNewLink = document.createElement ('a'); //  myNewLink.href = 'http://google.com'; // myNewLink.appendChild (document.createTextNode ('Visit Google')); // Ga naar Google // Nu kunnen we het aan de alinea toevoegen: myIntro.appendChild (myNewLink);

Er is ook een 'insertBefore' DOM-methode die voor zichzelf spreekt. Met behulp van deze twee methoden ('insertBefore' & 'appendChild') kunnen we onze eigen 'insertAfter' functie maken:

 // 'Target' is het element al in de DOM // 'Bullet' is het element dat u wilt invoegen functie insertAfter (target, bullet) target.nextSibling? target.parentNode.insertBefore (bullet, target.nextSibling): target.parentNode.appendChild (opsommingsteken);  // We gebruiken een ternaire operator in de bovenstaande functie: // Het formaat: VOORWAARDE? EXPRESSIE INDIEN WAAR: EXPRESSIE INDIEN ONWAAR;

Met de bovenstaande functie wordt gecontroleerd of de volgende broer of zus van het doel in de DOM bestaat, als deze bestaat, dan voegt deze het 'bullet'-knooppunt in vóór de volgende broer van het doel, anders neemt het aan dat het doelwit het laatste kind van een element is en dus het is prima om de kogel toe te voegen als een kind van de ouder. De DOM API geeft ons geen 'insertAfter'-methode omdat er geen behoefte aan is - we kunnen het zelf creëren.

Er is nogal wat meer te leren over het manipuleren van elementen binnen de DOM, maar het bovenstaande zou een voldoende basis moeten zijn waarop je kunt bouwen.

Evenementen

Browsergebeurtenissen vormen de kern van elke webtoepassing en de meeste JavaScript-verbeteringen. Het is door deze gebeurtenissen die we definiëren wanneer er iets gaat gebeuren. Als u een knop in uw document hebt en u een formuliervalidatie nodig hebt om plaats te vinden wanneer er op wordt geklikt, gebruikt u de 'klik'-gebeurtenis. Hieronder volgt een overzicht van de meeste standaard browser-evenementen:

Opmerking: zoals we de vorige keer hebben besproken, zijn de DOM en de JavaScript-taal twee afzonderlijke entiteiten. Browsergebeurtenissen maken deel uit van de DOM-API, ze maken geen deel uit van JavaScript.

Muis evenementen

  • 'MouseDown' - De gebeurtenis met de muis wordt geactiveerd wanneer het aanwijsapparaat (meestal een muis) naar beneden wordt gedrukt over een element.
  • 'MouseUp' - De mouse-upgebeurtenis wordt afgevuurd wanneer het aanwijsapparaat (meestal een muis) wordt losgelaten over een element.
  • 'Klik' - De klikgebeurtenis wordt gedefinieerd als een muisaanwijzer gevolgd door een muisup op exact dezelfde positie.
  • 'DblClick' - Deze gebeurtenis wordt geactiveerd wanneer een element tweemaal snel achter elkaar op dezelfde positie wordt geklikt.
  • 'Mouseover' - De mouseover-gebeurtenis wordt geactiveerd wanneer het aanwijsapparaat over een element wordt verplaatst.
  • 'MouseOut' - De mouseout-gebeurtenis wordt geactiveerd wanneer het aanwijsapparaat uit een element wordt verplaatst. (weg van een element)
  • 'Mousemove' - De mousemove-gebeurtenis wordt geactiveerd wanneer het aanwijsapparaat wordt verplaatst terwijl het boven een element zweeft.

Toetsenbord evenementen

  • 'toets indrukken' - Deze gebeurtenis wordt geactiveerd telkens wanneer op een toets op het toetsenbord wordt gedrukt.
  • 'toets neer' - Deze gebeurtenis wordt ook geactiveerd wanneer een toets wordt ingedrukt, deze loopt vóór de 'toetsaanslag'-gebeurtenis.
  • 'Keyup' - Deze gebeurtenis wordt afgevuurd wanneer een sleutel wordt vrijgegeven, na zowel de 'keydown'- als' keypress'-gebeurtenissen.

Formulier evenementen

  • 'Select' - Deze gebeurtenis wordt geactiveerd wanneer tekst in een tekstveld (invoer, tekstveld, enz.) Is geselecteerd.
  • 'verandering' - Deze gebeurtenis wordt afgevuurd wanneer een besturingselement de invoerfocus verliest en / of de waarde is gewijzigd sinds het verkrijgen van de focus.
  • 'Submit' - Deze gebeurtenis wordt afgevuurd wanneer een formulier wordt verzonden.
  • 'Reset' - Deze gebeurtenis wordt geactiveerd wanneer een formulier opnieuw wordt ingesteld.
  • 'focus' - Deze gebeurtenis wordt afgevuurd wanneer een element focus krijgt, meestal van een aanwijsapparaat.
  • 'Blur' - Deze gebeurtenis wordt afgevuurd wanneer een element focus verliest, meestal van een aanwijsapparaat.

Andere evenementen

  • 'laden' - Deze gebeurtenis wordt geactiveerd wanneer de user-agent alle inhoud in een document heeft geladen, inclusief inhoud, afbeeldingen, frames en objecten. Voor elementen, zoals 'IMG', wordt het weergegeven wanneer de betreffende inhoud is geladen.
  • 'Resize' - Deze gebeurtenis wordt geactiveerd wanneer de grootte van de documentweergave wordt gewijzigd. (dat wil zeggen wanneer de grootte van de browser wordt gewijzigd.)
  • 'rol' - Deze gebeurtenis wordt geactiveerd wanneer het document wordt gescrold.
  • 'lossen' - Deze gebeurtenis wordt geactiveerd wanneer de user-agent alle inhoud uit een venster of kader verwijdert, d.w.z. wanneer u een pagina verlaat.

Er zijn nog veel meer evenementen om uit te kiezen. De hierboven getoonde zijn de belangrijkste die je vaak tegenkomt in JavaScript-code. Houd er rekening mee dat sommige van hen subtiele verschillen tussen browsers hebben. Houd er ook rekening mee dat veel browsers eigen evenementen implementeren, er zijn bijvoorbeeld een flink aantal Gecko-specifieke evenementen, zoals 'DOMContentLoaded' of 'DOMMouseScroll' - hier kun je meer over lezen: https://developer.mozilla.org / nl / Gecko-Specific_DOM_Events

Afhandeling van gebeurtenissen

We hebben de feitelijke gebeurtenissen besproken, maar we moeten het proces van het koppelen van een functie aan een evenement nog bespreken. Dit is waar de magie gebeurt. De hierboven genoemde gebeurtenissen zullen allemaal plaatsvinden ongeacht of u JavaScript hebt geschreven, dus om hun kracht te benutten, moet u "gebeurtenishandlers" registreren. - Dit is een mooie term om een ​​functie te beschrijven die wordt gebruikt om een ​​evenement af te handelen. Hier is een eenvoudig voorbeeld met behulp van de basis- model voor evenementenregistratie (ook bekend als "registratie van traditionele evenementen"):

Basis evenementenregistratie:

  
 // JavaScript: var myElement = document.getElementById ('mijn knop'); // Deze functie is onze gebeurtenishandler: functieknopKlik op () alert ('U hebt zojuist op de knop geklikt!');  // Dit is het onderdeel voor evenementregistratie: myElement.onclick = buttonKlik;

We hebben een HTML-knop met een ID van 'mijn knop' en we hebben deze geopend met de opdracht 'document.getElementById'. Vervolgens maken we een nieuwe functie die later wordt toegewezen aan de eigenschap DOM van de knop 'on-liken'. Dat is alles wat er is!

Het model van de "basisgebeurtenisregistratie" is zo eenvoudig als het wordt. Je geeft het evenement dat je zoekt een voorvoegsel met 'aan' en opent het als een eigenschap van het element waarmee je werkt. Dit is in wezen de onopvallende versie van het doen van iets als dit (dat raad ik niet aan):

 

Inline-afhandeling van gebeurtenissen (met behulp van HTML-kenmerken) is zeer opdringerig en maakt uw website een stuk moeilijker te onderhouden. Het is beter om onopvallende JavaScript-code te gebruiken en deze allemaal in de respectieve '.js'-bestanden te plaatsen die in het document kunnen worden opgenomen als / wanneer nodig. Hoewel we het hebben over onopvallend JavaScript, wil ik de algemene misvatting corrigeren dat bibliotheken zoals jQuery het "mogelijk maken om onopvallend te coderen" - dit is niet waar. Wanneer u jQuery gebruikt, is het net zo gemakkelijk om dingen op de verkeerde manier te doen. De reden dat u geen inline-eventafhandeling zou moeten gebruiken, is exact hetzelfde als de reden waarom u geen inline CSS-stijlen (met behulp van) zou moeten toepassen.

Geavanceerde evenementenregistratie:

Laat deze naam je niet misleiden, alleen omdat het 'geavanceerd' wordt genoemd, betekent niet dat het beter te gebruiken is; in feite is de techniek die we hierboven bespraken ("basisgebeurtenisregistratie") meestal het meest geschikt. Het gebruik van de basistechniek heeft echter één belangrijke beperking; je kunt niet meer dan één functie aan een evenement binden. Dit is eigenlijk niet zo erg, omdat je gewoon een willekeurig aantal andere functies vanuit die ene functie kunt aanroepen, maar als je meer controle nodig hebt, dan is er een andere manier om handlers te registreren, voer dan het "geavanceerde evenementregistratiemodel" in.

Met dit model kunt u meerdere handlers aan een enkele gebeurtenis binden, wat betekent dat er meerdere functies worden uitgevoerd wanneer een gebeurtenis plaatsvindt. Bovendien kunt u met dit model eenvoudig alle gebonden gebeurtenishandlers verwijderen.

Strikt genomen zijn er twee verschillende modellen in deze categorie; de W3C's en Microsoft's. Het W3C-model wordt ondersteund door alle moderne browsers, behalve IE, en het model van Microsoft wordt alleen ondersteund door IE. Zo zou je het model van de W3C gebruiken:

 // FORMAT: target.addEventListener (type, functie, useCapture); // Voorbeeld: var myIntro = document.getElementById ('intro'); myIntro.addEventListener ('klik', introClick, false);

En hier is hetzelfde, maar voor IE (het model van Microsoft):

 // FORMAT: target.attachEvent ('on' + type, functie); // Voorbeeld: var myIntro = document.getElementById ('intro'); myIntro.attachEvent ('onclick', introClick);

En hier is de functie 'introClick':

 functie introClick () alert ('U hebt de alinea aangeklikt!'); 

Omdat beide modellen niet in alle browsers werken, is het een goed idee om ze beide te combineren in een aangepaste functie. Hier is een zeer eenvoudige 'addEvent' functie, die cross-browser werkt:

 functie addEvent (elem, type, fn) if (elem.attachEvent) elem.attachEvent ('on' + type, fn); terug te keren;  if (elem.addEventListener) elem.addEventListener (type, fn, false); 

De functie controleert de eigenschappen 'attachEvent' en 'addEventListener' en gebruikt vervolgens een van de modellen die afhankelijk zijn van die test. Beide modellen maken het mogelijk om ook event handlers te verwijderen, zoals getoond in deze 'removeEvent' functie:

 functie removeEvent (elem, type, fn) if (elem.detachEvent) elem.detachEvent ('on' + type, fn); terug te keren;  if (elem.removeEventListener) elem.removeEventListener (type, fn, false); 

U zou de volgende functies gebruiken:

 var myIntro = document.getElementById ('intro'); addEvent (myIntro, 'klik', functie () alert ('YOU CLICKED ME !!!'););

Merk op dat we een naamloze functie als de derde parameter hebben doorgegeven. Met JavaScript kunnen we functies definiëren en uitvoeren zonder ze te benoemen; functies van dit type worden "anonieme functies" genoemd en kunnen erg handig zijn, vooral als u een functie als parameter aan een andere functie moet doorgeven. We hadden zojuist onze 'introClick'-functie (eerder gedefinieerd) als de derde parameter kunnen instellen, maar soms is het handiger om het met een anonieme functie te doen.

Als u een actie alleen voor de eerste keer dat erop wordt geklikt wilt laten plaatsvinden, kunt u dit als volgt doen:

 // Merk op dat we de addEvent / removeEvent-functies // al hebben gedefinieerd (om ze te gebruiken moeten ze worden opgenomen) var myIntro = document.getElementById ('intro'); addEvent (myIntro, 'klik', oneClickOnly); function oneClickOnly () alert ('WOW!'); removeEvent (myIntro, 'click', oneClickOnly); 

We verwijderen de handler zodra het evenement voor de eerste keer wordt afgevuurd. We hebben geen anonieme functie in het bovenstaande voorbeeld kunnen gebruiken omdat we een verwijzing naar de functie ('oneClickOnly') moesten behouden, zodat we deze later konden verwijderen. Dat gezegd hebbende, is het eigenlijk mogelijk om te bereiken met een naamloze (anonieme) functie:

 addEvent (myIntro, 'klik', functie () alert ('WOW!'); removeEvent (myIntro, 'click', arguments.callee););

We zijn hier nogal brutaal door te verwijzen naar de 'callee' eigenschap van het 'argumenten'-object. Het object 'arguments' bevat alle doorgegeven parameters van elke functie en bevat ook een verwijzing naar de functie zelf ('callee'). Door dit te doen elimineren we de noodzaak om een ​​benoemde functie te definiëren (bijvoorbeeld de eerder getoonde 'oneClickOnly'-functie) volledig.

Afgezien van de voor de hand liggende syntactische verschillen tussen de implementatie van de W3C en Microsoft zijn er enkele andere discrepanties die het waard zijn op te merken. Wanneer u een functie aan een gebeurtenis koppelt, moet de functie worden uitgevoerd binnen de context van het element, en dus moet het 'dit' sleutelwoord binnen de functie verwijzen naar het element; met behulp van het basiseventregistratiemodel of het geavanceerde model van W3C werkt dit zonder fouten, maar de implementatie van Microsoft mislukt. Hier is een voorbeeld van wat jij moeten kunnen doen binnen event handling-functies:

 function myEventHandler () this.style.display = 'none';  // Werkt correct, 'dit' verwijst naar het element: myIntro.onclick = myEventHandler; // Werkt correct, 'dit' verwijst naar het element: myIntro.addEventListener ('click', myEventHandler, false); // WERKT NIET correct, 'dit' verwijst naar het Window-object: myIntro.attachEvent ('onclick', myEventHandler);

Er zijn een paar verschillende manieren om dit probleem te voorkomen / op te lossen. Verreweg de gemakkelijkste optie is om het basismodel te gebruiken - er zijn bijna geen inconsistenties tussen de browsers bij gebruik van dit model. Als je echter het geavanceerde model wilt gebruiken en je hebt het 'dit' sleutelwoord nodig om het element correct te verwijzen, dan zou je eens moeten kijken naar enkele van de meer geadopteerde 'addEvent'-functies, met name John Resig's of Dean Edward's gebruik niet eens het geavanceerde model, geweldig!).

Het gebeurtenisobject

Een belangrijk aspect van het afhandelen van gebeurtenissen, dat we nog moeten bespreken, is het evenementobject. Wanneer u een functie aan een gebeurtenis koppelt, dat wil zeggen telkens wanneer u een gebeurtenishandler maakt, wordt de functie een object doorgegeven. Dit gebeurt van nature, dus je hoeft geen actie te ondernemen om het te induceren. Dit gebeurtenisobject bevat een verscheidenheid aan informatie over de gebeurtenis die net heeft plaatsgevonden; het bevat ook uitvoerbare methoden die verschillende gedragseffecten hebben op de gebeurtenis. Maar, niet verwonderlijk, Microsoft koos zijn eigen manier om deze "functie" te implementeren; IE-browsers geven dit gebeurtenisobject niet door, maar moeten het als een eigenschap van het globale vensterobject openen; dit is niet echt een probleem, het is alleen maar vervelend:

 function myEventHandler (e) // Let op het 'e'-argument ... // Wanneer deze functie wordt aangeroepen, als gevolg van het event // firing, wordt het gebeurtenisobject doorgegeven (in W3C-compatibele agents) // Let's make' e 'cross-browser vriendelijk: e = e || window.event; // Nu kunnen we veilig verwijzen naar 'e' in alle moderne browsers.  // We zouden onze functie binden aan een evenement hier beneden ... 

Om het bestaan ​​van het 'e'-object (het' Event-object ') te controleren, gebruiken we een OR-operator (logisch) die in feite het volgende dicteert: als' e 'een waarde' falsy 'is (null, undefined, 0 etc.) en wijs dan 'window.event' toe aan 'e'; gebruik anders gewoon 'e'. Dit is een snelle en eenvoudige manier om het echte Event-object in een cross-browseromgeving te krijgen. Als u niet vertrouwd bent met het gebruik van logische operatoren buiten een IF-instructie, dan kan dit construct meer bij u passen:

 if (! e) e = window.event;  // Geen ELSE-instructie is nodig omdat 'e' // al in andere browsers is gedefinieerd

Enkele van de meest bruikbare opdrachten en eigenschappen van dit gebeurtenisobject zijn helaas inconsistent geïmplementeerd in browsers (namelijk IE versus alle andere). Het annuleren van de standaardactie van een gebeurtenis kan bijvoorbeeld worden bereikt met de methode 'preventDefault ()' van het object Event, maar in IE kan dit alleen worden bereikt met de eigenschap 'returnValue' van het object. Dus, nogmaals, we moeten beide gebruiken om alle browsers te accommoderen:

 function myEventHandler (e) e = e || window.event; // Voorkomen dat de standaardactie van een gebeurtenis plaatsvindt: if (e.preventDefault) e.preventDefault ();  else e.returnValue = false; 

De standaardactie van een gebeurtenis is wat normaal gebeurt als gevolg van het afvuren van gebeurtenissen. Wanneer u op een ankerkoppeling klikt, is de standaardactie dat de browser naar de locatie navigeert die is opgegeven in het kenmerk 'href' van die link. Maar soms wilt u deze standaardactie uitschakelen.

De 'returnValue' / 'preventDefault' ergernis is niet alleen; veel andere eigenschappen van het Event-object zijn inconsistent geïmplementeerd, dus dit if / else / of controlemodel is een vereiste taak.

Veel van de JavaScript-bibliotheken van tegenwoordig normaliseren het gebeurtenisobject, wat betekent dat commando's als 'e.preventDefault' beschikbaar zijn in IE, hoewel u er rekening mee moet houden dat de eigenschap 'returnValue' achter de schermen nog steeds wordt gebruikt.

Evenement bubbelen

Geborreld borrelen, ook wel bekend als "gebeurtenisvoortplanting", is wanneer een gebeurtenis wordt afgevuurd en vervolgens "gebobbeld" door de DOM. Het eerste ding om op te merken is dat niet alle evenementen bubbelen, maar voor degenen die dat doen, hier is hoe het werkt:

De gebeurtenis vuurt op het doelelement. De gebeurtenis vuurt vervolgens op elke voorouder van dat element - de gebeurtenis borrelt omhoog door de DOM totdat het het bovenste element bereikt:


Evenement bubbling, geïllustreerd

Zoals in de bovenstaande afbeelding wordt getoond, wordt als er op een anker in een alinea wordt geklikt, de klikgebeurtenis van het anker eerst geactiveerd en vervolgens, waarna de alinea-klikgebeurtenis wordt geactiveerd, enz. Totdat het hoofdelement is bereikt (de hoofdtekst is het hoogste DOM-element die een klikgebeurtenis heeft).

Deze gebeurtenissen worden in die volgorde geactiveerd, ze gebeuren niet allemaal tegelijkertijd.

Het idee van event bubbling is misschien niet zo logisch, maar uiteindelijk wordt duidelijk dat het een fundamenteel onderdeel is van wat we als 'normaal gedrag' beschouwen. Wanneer u een handler aan de klikgebeurtenis van de alinea koppelt, verwacht u dat deze wordt geactiveerd wanneer op de alinea wordt geklikt, toch? Welnu, dat is precies wat 'event bubbling' garandeert - als de alinea meerdere kinderen heeft, (s, s, s) en zelfs als er op wordt geklikt, wordt het evenement opgeblazen tot aan de alinea.

Dit borrelgedrag kan ALTIJD tijdens het proces worden gestopt. Dus als u alleen wilt dat de gebeurtenis naar de alinea borrelt maar niet verder (niet naar het hoofdknooppunt), kunt u een andere nuttige methode gebruiken die u vindt in het gebeurtenisobject, "stopPropagation":

 function myParagraphEventHandler (e) e = e || window.event; // Stop het optreden van borrelen: if (e.stopPropagation) // W3C-compatibele browsers: e.stopPropagation ();  else // IE: e.cancelBubble = true;  // De functie is gebonden aan de klikgebeurtenis van de alinea: // Gebruikmaken van onze op maat gemaakte addEvent-functie: addEvent (document.getElementsByTagName ('p') [0], 'click', myParagraphEventHandler);

Evenement delegatie

Stel dat u bijvoorbeeld een enorme tabel met veel rijen met gegevens hebt. Binden van een click event-handler voor elke single kan een gevaarlijke onderneming zijn, vooral vanwege het negatieve effect op de prestaties. Een gebruikelijke manier om dit probleem te bestrijden, is door "gebeurtenisafvaardiging" te gebruiken. Gebeurtenisdelegatie beschrijft het proces van het toepassen van een gebeurtenishandler op een containerelement en dat vervolgens te gebruiken als basis voor alle onderliggende elementen. Door de eigenschap 'target' ('srcElement' in IE) te testen van het gebeurtenisobject, kunnen we het echte geklikte element bepalen.

 var myTable = document.getElementById ('mijn-tabel'); myTable.onclick = function () // Omgaan met browser incompatibiliteit: e = e || window.event; var targetNode = e.target || e.srcElement; // Test of het een TR was waarop is geklikt: if (targetNode.nodeName.toLowerCase () === 'tr') alert ('U hebt een tabelrij aangeklikt!'); 

Het delegeren van evenementen is afhankelijk van borrelende gebeurtenissen. De bovenstaande code zou niet werken als het bellen was gestopt voordat het 'tafel'-knooppunt werd bereikt.

Dat is het voor vandaag!

We hebben besproken hoe DOM-elementen kunnen worden gemanipuleerd en we hebben in vrij grote mate het browsergebeurtenismodel besproken. Ik hoop dat je vandaag iets hebt geleerd! Zoals gewoonlijk, als u vragen heeft, aarzel dan niet om te vragen.

  • Abonneer u op de NETTUTS RSS-feed voor meer dagelijkse webontwikkelingen, tuts en artikelen.