Bijna alles wat u in JavaScript doet, zou moeten beginnen wanneer er iets gebeurt: de gebruiker klikt op een knop, zweeft over een menu, drukt op een toets, u krijgt het idee. Het is vrij eenvoudig te doen met bibliotheken zoals jQuery, maar weet je hoe je evenementen in raw JavaScript moet aansluiten? Vandaag zal ik je dat precies leren!
JavaScript-evenementen afhandelen is geen rocket science. Natuurlijk zijn er browser verschillen (wat had je verwacht?), Maar als je het eenmaal onder de knie hebt en je eigen helper-functies hebt gebouwd om zelfs het speelveld te verbeteren, zul je blij zijn dat je het weet. Zelfs als je nog steeds van plan bent om een bibliotheek voor dit soort dingen te gebruiken, is het goed om te weten wat er zich onder de oppervlakte afspeelt. Daar gaan we.
De meest elementaire gebeurtenisafhandeling in JavaScript is gebeurtenisafhandeling op niveau 0. Het is vrij eenvoudig: wijs gewoon je functie toe aan de eigenschap event van het element. Let op:
var element = document.getElementById ('myElement'); element.onclick = function () alert ('uw functie hier'); ;
Zodra ik het element heb, stel ik de bij klikken
eigenschap gelijk aan een functie. Nu wanneer element
is geklikt, die functie zal worden uitgevoerd en we zullen een waarschuwingsvenster zien.
Maar hoe wist ik het te gebruiken? bij klikken
? Je kunt een lijst met beschikbare evenementen krijgen op Wikipedia. Het mooie aan de methode Level 0 is dat deze wordt ondersteund in alle browsers die tegenwoordig veel worden gebruikt. Het nadeel is dat je elke gebeurtenis maar één keer met elk element kunt registreren. Dit veroorzaakt dus maar één melding:
element.onclick = function () alert ('function 1'); ; element.onclick = function () alert ('I overschrijf functie 1');
Alleen de tweede functie wordt uitgevoerd wanneer op het element wordt geklikt, omdat we de eigenschap onclick opnieuw hebben toegewezen. Om een gebeurtenishandler te verwijderen, kunnen we deze gewoon op nul zetten.
element.onclick = null;
Hoewel het alleen basisfunctionaliteit biedt, zorgt de consistente ondersteuning in alle browsers ervoor dat gebeurtenis 0 van niveau 1 een geldige optie is voor supereenvoudige projecten.
Nu je JavaScript-gebeurtenissen opwarmt, bespreken we twee belangrijke facetten voordat we overgaan op betere technieken: het gebeurtenisobject en het deze
trefwoord. Wanneer een gebeurtenis wordt uitgevoerd, is er veel informatie over de gebeurtenis die u misschien wilt weten: welke toets is ingedrukt? op welk element is geklikt? heeft de gebruiker met de linker-, rechter- of middelste knop geklikt? Al deze gegevens en meer worden opgeslagen in een gebeurtenisobject. Voor alle browsers behalve Internet Explorer kunt u bij dit object komen door het door te geven als een parameter voor de verwerkingsfunctie. In IE kun je het krijgen van de globale variabele window.event
. Het is niet moeilijk om dit verschil op te lossen.
function myFunction (evt) evt = evt || window.event; / * ... * / element.onclick = myFunction;
myFunction
neemt de parameter event voor alle goede browsers en we wijzen deze toe aan window.event
als evt
bestaat niet We zullen een paar later naar enkele eigenschappen van het gebeurtenisobject kijken.
De deze
keywork is belangrijk binnen event-handling-functies; het verwijst naar het element dat de gebeurtenis heeft ontvangen.
element.onclick = function () this.style.backgroundColor = 'red'; // same als element.style.backgroundColor = 'red';
Helaas, in Internet Explorer, deze
verwijst niet naar het geacteerde element; het verwijst naar het vensterobject. Dat is nutteloos, maar we zullen een manier bekijken om dat in een beetje te verhelpen.
Behandeling van gebeurtenissen op niveau 2 is de W3C-specificatie voor DOM-evenementen. Het is vrij simpel, eigenlijk.
element.addEventListener ('mouseover', myFunction, false);
De methode wordt genoemd addEventListener
. De eerste parameter is het type evenement waarnaar we willen luisteren. Meestal is het dezelfde naam als de Level 0 -gebeurtenissen, zonder het voorvoegsel 'aan'. De tweede parameter is een functienaam of de functie zelf. De laatste parameter bepaalt of we vastleggen of niet; we zullen dit in een moment bespreken.
Een van de grote voordelen van het gebruik addEventListener
is dat we nu meerdere gebeurtenissen kunnen toewijzen voor een enkele gebeurtenis op een enkel element:
element.addEventListener ('dblclick', logSuccessToConsole, false); element.addEventListener ('dblclick', function () console.log ('deze functie doens \' t negeer de eerste. ');, false);
Gebruik deze functie om deze handlers te verwijderen removeEventListener
. Dus, om de functie die we hierboven hebben toegevoegd te verwijderen, doen we dit:
element.removeEventListener ('dblclick', logSuccessToConsole, false);
De laatste parameter in addEventListner
en removeEventListener
is een boolean die bepaalt of we de gebeurtenis in de vastleggende of borrelende fase starten. Dit is wat dat betekent:
Wanneer u op een element klikt, klikt u ook op elk van de voorouderelementen.
Werk opslaan
Als ik op de overspanning # besparen
, Ik heb ook geklikt div # toolbar
, div # wrapper
, en lichaam
. Als een van deze elementen gebeurtenislisteners heeft die naar klikken luisteren, worden hun respectieve functies gebeld. Maar welke volgorde moeten ze worden genoemd? Dat is wat de laatste parameter beslist. In de W3C-specificatie zou ons klikgebeurtenis beginnen bij de lichaam
en ga door de ketting tot het de overspanning # besparen
; dat is de fase van het vastleggen. Dan gaat het van de overspanning # besparen
terug naar de lichaam
; dat is het bubbelende stadium. Dit is gemakkelijk te onthouden, omdat luchtbellen naar boven drijven. Niet alle evenementen bubbelen; dat Wikipedia-diagram u zal vertellen welke doen en welke niet.
Dus als de capture-parameter is ingesteld op waar
, de gebeurtenis wordt onderweg naar beneden geactiveerd; als het is ingesteld op vals
, het wordt geactiveerd op de weg naar boven.
Het is je misschien al opgevallen dat tot nu toe al mijn voorbeelden het vastleggen op false hebben vastgelegd, dus de gebeurtenis wordt getriggerd in het bubblingstadium. Dit komt omdat Internet Explorer geen capture-fase heeft. In IE borrelen alleen evenementen.
IE heeft zijn eigen, eigen manier van werken met evenementen. Het gebruikt attachEvent
.
element.attachEvent ('onclick', runThisFunction);
Omdat IE-gebeurtenissen alleen bubbelen, hebt u de derde variabele niet nodig. De eerste twee zijn hetzelfde als met addEventListener
, met de grote uitzondering dat IE dat 'op'-voorvoegsel voor het gebeurtenistype vereist. Natuurlijk kunt u met dit model meerdere gebeurtenissen van één soort aan een individueel element toewijzen. Gebruik. Om gebeurtenissen te verwijderen detachEvent
.
element.detachEvent ('onclick', runThisFunction);
Wat als uw elementen niet willen dat hun ouders te weten komen over hun evenementen? Het is niet moeilijk om je te verstoppen. In IE, gebruikt u de cancelBubble
eigenschap op het gebeurtenisobject die wordt doorgegeven aan de opgeroepen functie. Voor de rest kunt u de stopPropogation
methode, ook op het gebeurtenisobject.
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation ();
De stopPropogation
methode zal ook gebeurtenissen in hun tracks stoppen tijdens de opnamefase.
Ik durf te wedden dat de meeste eigenschappen van het evenementobject ongebruikt blijven, maar er zijn een paar geselecteerde die u van onschatbare waarde vindt. Laten we die paar bekijken.
De doelwit
eigenschap is het diepste element waarop is geklikt. In de bovenstaande afbeelding kunt u zien dat ik heb geklikt h1 # toets
. In IE wordt deze eigenschap genoemd srcElement
; om bij deze woning te komen, doe zoiets als dit:
var target = e.target || e.srcElement;
De currentTarget
property is het element dat de gebeurtenis nu heeft. In die schermafbeelding is de currentTarget
is div # wrapper
. Dit betekent dat ik heb geklikt h1 # toets
, maar het gebeurtenisobject is in de console gelogd in de functie die wordt aangeroepen door de div # wrapper
de gebeurtenis luisteraar.
Maar dit zal je voor een lus gooien: IE heeft geen currentTarget-eigenschap, of iets dergelijks. Herinnerend aan het feit dat IE niet eens verhuurt deze
gelijk aan het element dat de gebeurtenis activeert, dit betekent dat we geen mogelijkheid hebben om het element te krijgen dat de gebeurtenis heeft geactiveerd toen het opborrelt (wat betekent dat er op een afstammeling van het element is geklikt). Verward? Misschien helpt een voorbeeld: als we in Internet Explorer deze HTML hebben ...
Knop
... en deze gebeurtenishandler ...
var par = document.getElementById ('parent'); parent.attachEvent ('onclick', doSomething);
... dan, wanneer we op klikken overspanning # kind
en het evenement bubbelt omhoog naar div # ouder
, we kunnen niet van binnen uit de functie komen doe iets
om bij het element te komen (in dit geval, div # ouder
) het evenement is geactiveerd.
Er zijn andere eigenschappen in het gebeurtenisobject die u handig vindt, afhankelijk van de situatie. Op een toetsenbordgebeurtenis, (keyup, keydown, keypress) zul je de sleutelcode
en de charCode
. U kunt zien of de gebruiker de alt-, shift- of ctrl-toets (cmd) ingedrukt hield terwijl u op / klikte. Verken de gebeurtenisobjecten van verschillende evenementen en zie waar je mee moet werken!
We zijn tot nu toe twee hoofdproblemen tegengekomen bij onze studie van evenementen.
currentTarget
eigendom, en de deze
object verwijst naar het vensterobject.Om deze problemen op te lossen, bouwen we een twee functies met ondersteuning voor meerdere browsers, een om gebeurtenissen te koppelen en een om ze te verwijderen.
We beginnen met Voeg evenement toe
; hier is de eerste ronde:
var addEvent = function (element, type, fn) if (element.attachEvent) element.attachEvent ('on' + type, fn); else element.addEventListener (type, fn, false);
Ik draag een anonieme functie toe aan de variabele Voeg evenement toe
om redenen die u zo meteen zult zien. Het enige wat we moeten doen is controleren om te zien of het element de attachEvent
methode. Als dat zo is, bevinden we ons in IE en gebruiken we die methode. Zo niet, dan kunnen we gebruiken addEventListener
.
Dit lost echter niet het feit op dat we geen toegang hebben tot het hoofdelement van de gebeurtenis in IE. Om dit te doen, zullen we de functie een attribuut maken op het element; op die manier wordt het waargenomen als een methode van het element, en deze
zal het element evenaren. Ja, ik weet het, briljant, is het niet? Nou, ik kan geen enkele eer aan: dit idee komt van een blogpost van John Resig.
var addEvent = function (element, type, fn) if (element.attachEvent) element ['e' + type + fn] = fn; element [type + fn] = function () element ['e' + type + fn] (window.event); element.attachEvent ('on' + type, element [type + fn]); else element.addEventListener (type, fn, false);
De eerste extra regel (element ['e' + type + fn] = fn;
) maakt de functie een methode van het element, dus dat deze
zal nu het element evenaren. De tweede regel is een functie die de methode uitvoert en in het window.event-object doorgeeft. Dit bespaart u de extra stap van het controleren van de parameter van het gebeurtenisobject binnen uw functie. Merk ten slotte op dat we de functieparameter hebben gewijzigd in attachEvent
methode om element [Type fn +]
.
Dat lost onze twee problemen op. We kunnen nu onze gebruiken Voeg evenement toe
functie in alle browsers met een zo veel mogelijk vergelijkbare ervaring. Maar er is een kleine optimalisatie die we graag willen maken.
Merk op dat elke keer onze Voeg evenement toe
functie wordt aangeroepen, wordt er gecontroleerd op de attachEvent
methode. Er is geen reden waarom we dit meer dan eens zouden moeten controleren, ongeacht hoeveel evenementen we willen registreren. We kunnen een handige truc gebruiken waarmee we opnieuw kunnen schrijven Voeg evenement toe
.
var addEvent = function (el, type, fn) if (el.attachEvent) addEvent = function (el, type, fn) el ['e' + type + fn] = fn; el [type + fn] = functie () el ['e' + type + fn] (window.event); ; el.attachEvent ('on' + type, el [type + fn]); else addEvent = function (el, type, fn) el.addEventListener (type, fn, false); addEvent (el, type, fn);
Nu, als het Voeg evenement toe
methode is gevonden, we zullen opnieuw schrijven Voeg evenement toe
om alleen de IE-onderdelen op te nemen; zo niet, dan nemen we gewoon de goede browseronderdelen op.
Onze removeEvent
functie zal erg op elkaar lijken:
var removeEvent = function (element, type, fn) if (element.detachEvent) removeEvent = function (element, type, fn) element.detachEvent ('on' + type, el [type + fn]); element [type + fn] = null; else removeEvent = function (element, type, fn) element.removeEventListener (type, fn, false); removeEvent (element, type, fn);
Dat is het voor onze event-functies voor cross-browsers. Er is echter één ding dat ik niet leuk aan hen vind: de functies zijn geen methoden van de elementen; in plaats daarvan is het element een parameter. Ik weet dat het gewoon een kwestie van stijl is, maar ik vind het leuk
btn.addEvent ('klik', doe dit);
beter dan
addEvent (btn, 'klik', doThis);
We kunnen dit doen door onze functies hierin in te pakken:
var E = Element.prototype; E.addEvent = function (type, fn) addEvent (this, type, fn); E.removeEvent = function (type, fn) removeEvent (this, type, fn);
Dit werkt in alle moderne browsers, evenals IE8; IE7 en IE6 stikken in Element
. Het hangt van je publiek af; graag of niet!
Nu dat je alles weet over JavaScript-evenementen, haast je niet en vul je volgende project met gebeurtenislisteners. Als je veel elementen hebt die reageren op hetzelfde type evenement (zeg bijvoorbeeld klik), is het verstandiger om te profiteren van borrelen. U kunt gewoon een gebeurtenislistener toevoegen aan een voorouderelement, zelfs het hoofdgedeelte, en de eigenschap target / srcElement op het gebeurtenisobject gebruiken om erachter te komen op welk dieper element is geklikt. Dit wordt gebeurtenisdelegatie genoemd. Hier is een nutteloos voorbeeld:
Hier is wat HTML:
We kunnen afspraakafgifte gebruiken om klikken naar elk te verwerken li
:
functie navigatie (e) var el = e.target || e.srcElement; switch (el.id) case 'home': alert ('go home'); breken; case 'portfolio': alert ('bekijk mijn producten'); breken; case 'about': alert ('al die walgelijke details'); breken; case 'contact': alert ('Ik ben gevleid dat je graag wilt praten'); breken; standaard: waarschuwing ('hoe ben je hier terechtgekomen?'); var nav = document.getElementById ('nav'); addEvent (nav, 'klik', navigatie);
We gebruiken een switch / case-statement om naar de id van het dieper geklikte element te kijken. Vervolgens doen we iets dienovereenkomstig.
Dus nu kun je JavaScript-evenementen gebruiken met de beste ervan. Veel plezier ermee en stel vragen in de opmerkingen!