En av de vanligste oppgavene i webutvikling er hendelsehåndtering. Vår JavaScript-kode lytter vanligvis til hendelser som sendes av DOM-elementene.
Slik får vi informasjon fra brukeren: Det vil si, han eller hun klikker, typer, samhandler med siden vår, og vi må vite når dette skjer. Å legge til hendelseslyttere ser trivielt ut, men det kan være en tøff prosess.
I denne artikkelen vil vi se et real-case problem og sin 1.6K løsning.
En venn av meg jobber som junior utvikler. Som sådan har han ikke mye erfaring med vanilla JavaScript; Han har imidlertid måttet begynne å bruke rammer som AngularJS og Ember uten å ha den grunnleggende forståelsen av DOM-til-JavaScript-forhold. I løpet av sin tid som junior utvikler ble han ansvarlig for et lite prosjekt: En enkelt side kampanje nettsteder med nesten ingen JavaScript involvert. Han møtte et lite, men veldig interessant problem som til slutt fører meg til å skrive Bubble.js.
Tenk deg at vi har en popup. Et pent stylet Her er koden vi bruker til å vise en melding: Vi har en annen funksjon For eksempel, si at vi må implementere tilleggslogikk hvis problemene kommer i en etter en. La oss si at vi må legge to knapper til innholdet i popup-vinduet - Ja og Nei. Så, hvordan vet vi at brukeren klikker på dem? Vi må legge til hendelseslyttere til hver enkelt kobling. For eksempel: Koden ovenfor fungerer i løpet av første løp. Hva om vi trenger en ny knapp, eller enda verre, hva om vi trenger en annen type knapp? Det er, hva hvis vi skulle fortsette å bruke Her er hvor problemer blir synlige: Det må være en bedre måte å gjøre dette på. Ja, det er en bedre tilnærming. Og nei, løsningen er ikke å bruke et rammeverk. Før du avslører svaret, la oss snakke litt om hendelsene i DOM-treet. Hendelser er en viktig del av webutviklingen. De legger til interaktivitet i våre applikasjoner og fungerer som en bro mellom forretningslogikken og brukeren. Hvert DOM-element kan sende hendelser. Alt vi trenger å gjøre er å abonnere på disse hendelsene og behandle det mottatte Event-objektet. Det er et begrep hendelse propagasjon som står bak hendelse bobler og hendelsesfangst begge er to måter å behandle hendelser i DOM. La oss bruke følgende oppføring og se forskjellen mellom dem. Vi vil legge ved Når vi trykker på linken, ser vi følgende utgang i konsollen: Så, faktisk, mottar begge elementene Ved bruk av Noen ganger kan det hende at vi må reversere ordren og få hendelsen tatt av det ytre elementet. For å oppnå dette må vi bruke en tredje parameter i Slik behandler nettleseren hendelsene når vi samhandler med siden. Ok, så hvorfor brukte vi en del av artikkelen som snakket om å boble og fange. Vi nevnte dem fordi boblende er svaret på våre problemer med popupen. Vi bør sette hendelseslytterne ikke til koblingene, men til Ved å følge denne fremgangsmåten eliminerer vi problemene som er oppført i begynnelsen. Koden ovenfor er bedre enn den vi startet med. Fungerer likevel ikke på samme måte. Som vi sa, Vi hentet verdien av Det er imidlertid ikke en god idé å bruke Vår kode blir også litt bedre. Vi kan fjerne anførselstegnene som brukes i Resultatet kunne ses i denne JSBin. Jeg brukte løsningen over i flere prosjekter, så det var fornuftig å pakke det inn i et bibliotek. Den kalles Bubble.js, og den er tilgjengelig i GitHub. Det er 1,6k fil som gjør akkurat det vi gjorde over. La oss forvandle vårt popup-eksempel til bruk I stedet for Når vi inkluderer Det finnes også en alternativ syntaks: Som standard, JavaScript-håndtereren mottar fortsatt Event-objektet. Så, i dette tilfellet kan vi vise teksten til feltet: Noen ganger trenger vi ikke å fange en, men mange hendelser som sendes av det samme elementet. Finn den siste varianten i et JSBin her. Løsningen som er gitt i denne artikkelen er helt avhengig av hendelsen som bobler. I noen tilfeller For eksempel: Hvis vi legger musen over "velg" og utfører et klikk, er elementet som sender hendelsen ikke det Ganske vist er kommunikasjon med DOM en viktig del av vår applikasjonsutvikling, men det er en vanlig praksis at vi bruker rammer bare for å omgå den kommunikasjonen. Vi liker ikke å legge til lyttere igjen og igjen. Vi liker ikke å feilsøke merkelige dobbelthendelse-skyte bugs. Sannheten er at hvis vi vet hvordan nettleseren fungerer, kan vi eliminere disse problemene. Bubble.js er bare ett resultat av få timers lesing og en times koding - det er vår 1.6K løsning på et av de vanligste problemene.var popup = document.querySelector ('popup'); var showMessage = funksjon (msg) popup.style.display = 'block'; popup.innerHTML = msg; ... showMessage ('Laster inn. Vennligst vent.');
hideMessage
som endrer vise
eiendom til ingen
og gjemmer popupen. Tilnærmingen kan fungere i det mest generiske tilfellet, men har fortsatt noen problemer. var content = 'Er du sikker?
'; innhold + = 'Ja'; innhold + = 'Nei'; showMessage (innhold); var addListeners = funksjon (yesCB, noCB) popup.querySelector ('popup - yes'). addEventListener ('klikk', yesCB); popup.querySelector ('popup - no'). addEventListener ('klikk', noCB); showMessage (innhold); addListeners (function () console.log ('Yes button clicked');, funksjon () console.log ('Ingen knapp klikket'););
elementer, men med forskjellige klassenavn? Vi kan ikke bruke det samme
addListeners
funksjon, og det er irriterende å lage en ny metode for hver variant av popup.
Vis melding
kall. Vi må tenke på det hele tiden og synkronisere de to prosessene.popup
variabel. Vi må ringe det querySelector
funksjon i stedet for document.querySelector
. Ellers kan vi velge et feil element.addEventListener
samtaler. Det er ikke tørt i det hele tatt.Forstå hendelseshåndtering
klikk
hendelseshåndterer til begge elementene. Men fordi det er nestet inn i hverandre, vil de begge motta klikk
begivenhet.document.querySelector ('. wrapper'). addEventListener ('klikk', funksjon (e) console.log ('wrapper clicked');); document.querySelector ('a'). addEventListener ('klikk', funksjon (e) console.log ('et klikk'););
en klikket .wrapper klikket
klikk
begivenhet. Først, lenken og deretter stopPropagation
metode: document.querySelector ('a'). addEventListener ('klikk', funksjon (e) e.stopPropagation (); console.log ('et klikkt'););
stopPropagation
funksjon, indikerer vi at hendelsen ikke skal sendes til foreldrene.addEventListener
. Hvis vi passerer ekte
Som en verdi vil vi gjøre eventilasjonsfangst. For eksempel:document.querySelector ('. wrapper'). addEventListener ('klikk', funksjon (e) console.log ('wrapper clicked');, true); document.querySelector ('a'). addEventListener ('klikk', funksjon (e) console.log ('et klikk');, true);
Løsningen
var content = 'Er du sikker?
'; innhold + = 'Ja'; innhold + = 'Nei'; var addListeners = function () popup.addEventListener ('klikk', funksjon (e) var link = e.target;); showMessage (innhold); addListeners ();
Vis melding
er kalt. Så lenge som popup
variabel er i live vil vi fange hendelsene.addListeners
en gang bruker vi popup
variabel også en gang. Vi behøver ikke å beholde det eller overføre det mellom metodene.Vis melding
. Vi har tilgang til det klikket ankeret i det e.target
peker på det pressede elementet.e.target
peker til det klikket stikkord. Så, vi vil bruke det for å skille mellom Ja og Nei knapper.
var addListeners = funksjon (tilbakeringinger) popup.addEventListener ('klikk', funksjon (e) var link = e.target; var buttonType = link.getAttribute ('class'); hvis (tilbakeringinger [buttonType]) callbacks [ buttonType] (e);); ... addListeners ('popup - yes': funksjon () console.log ('Yes');, 'popup - no': funksjon () console.log ('Nei');) ;
klasse
Tilordne og bruk det som en nøkkel. De ulike klassene peker på forskjellige tilbakekallinger. klasse
Egenskap. Det er reservert for å bruke visuelle stiler til elementet, og verdien kan endres når som helst. Som JavaScript-utviklere bør vi bruke data
egenskaper.var content = 'Er du sikker?
'; innhold + = 'Ja'; innhold + = 'Nei';addListeners
funksjon:addListeners (yes: function () console.log ('Yes');, nei: funksjon () console.log ('Nei'););
Bubble.js
Bubble.js
. Det første vi må bytte, er den brukte merkingen:var content = 'Er du sikker?
'; innhold + = 'Ja'; innhold + = 'Nei';data-handling
vi burde bruke data-boble-handling
. bubble.min.js
På vår side har vi en global boble
funksjon tilgjengelig. Den aksepterer en DOM-elementvelger og returnerer bibliotekets API. De på
Metoden er den som legger til lytterne:boble ('popup') .on ('ja', funksjon () console.log ('Ja');) .on ('nei', funksjon () console.log ('Nei'); );
boble ('popup'). på (Ja: funksjon () console.log ('Ja');, nei: funksjon () console.log ('Nei'););
Bubble.js
lytter etter klikk
hendelser, men det er et alternativ å endre det. La oss legge til et inntastingsfelt og lytter etter det keyup
begivenhet:boble ('popup'). på (... input: funksjon (e) console.log ('Ny verdi:' + e.target.value););
data-boble-handling
aksepterer flere verdier skilt med komma:fallbacks
e.target
Kan ikke peke på elementet vi trenger. tag men
span
element.Sammendrag