Kuidas tuvastada JavaScripti klahvivajutusi

Foto autor Aleksandar Cvetanovic saidil Unsplash

JavaScripti üks enim kasutatud funktsioone on võime reageerida mitmesugustele sündmustele, mis võivad ilmneda kasutaja suheldes veebilehega. Tegelikult oli JavaScripti idee juba selle ilmumisel muuta veebilehti dünaamiliseks, lisades neile interaktiivsust. JavaScripti abil saame reageerida siis, kui kasutaja klõpsab konkreetsel lehe osal, klahvi vajutamisel, hiire liikumisel, lehe laadimisel, elemendi fokuseerimisel jne.

Kõigi saadaolevate JavaScripti sündmuste loendi leiate sellel MDN-i lehelt.

Ehkki täna saab JavaScripti abil teha palju rohkem, kasutatakse seda interaktiivsuse lisamise põhifunktsiooni veebilehele endiselt laialdaselt, et pakkuda kasutajatele rikkalikke ja huvitavaid kogemusi.

Selles artiklis uurime, kuidas saaksime JavaScripti kasutada klaviatuurisündmustele reageerimiseks, täpsemalt kuidas reageerida kasutaja sisestatud konkreetsele klahvijadale. Niisiis, kui kasutaja vajutab klahvikombinatsiooni, võib veebileht näidata mõnda sisu, näiteks avada menüü või moodus, see võib muuta lehe stiili või teha muid teie ette kujutatavaid toiminguid, mis jäävad JavaScripti võimaluste piiresse.

Enne kui alustame, tahan lihtsalt juhtida tähelepanu sellele, et kasutan mõnda ES6 funktsiooni, näiteks const and let, hajutamisoperaator (...), noolefunktsioonid jne. Kui te pole nendega tuttav, siis lugege lisamiseks pakutavaid linke rohkem.

Mida me ehitame?

Selle artikli jaoks olen otsustanud muuta lehe elementi oma taustapilti kasutaja sisestatud klahvide järjestuse põhjal. Seega tegeleme põhimõtteliselt stiiliga, miski pole liiga ulmeline. Lisame ka mõned tekstiuuendused, et tutvustamisviis oleks rikkalikum ja kasutajale rohkem teavet pakutaks.

Minu idee oli kasutada klahvijärjestusi, mida kasutatakse petukoodina vanas FPS-i mängus Doom ja Doom 2. Põhimõtteliselt, kui kasutaja klahvikombinatsiooni tipib, võimaldab mäng kasutajale teatud eeliseid, näiteks rohkem laskemoona, rohkem tervist , haavatavus jne

Koostatavas näites teeme lehe elemendi taustpildi muutmiseks vastavalt kasutaja sisestatud võtmejadale. Demot saab vaadata ja proovida siit.

Põhiprojekt

Et keskenduda ainult JavaScriptile, olen projekti jaoks koostanud täieliku HTML-i ja CSS-i ning linkinud JavaScripti faili, mis sisaldab ainult konsoolilogi, et veenduda selle toimimises. Algsed projektifailid saate alla laadida siit või luua oma, kui soovite, et see oleks tehtud omal moel.

Siin on meie JavaScripti sisu kiire jaotus.

See on üsna lihtne, lisame dokumendi sündmuste kuulaja, mis ootab, kuni DOM on täielikult laaditud, ja helistab siis tagasihelistamise funktsioonile. Tagasihelistamisfunktsioonil on praegu ainult käsk „kasuta rangelt” ja konsoolilogi, et kontrollida, kas fail on õigesti lingitud HTML-i lehele.

Me võime selle sündmusekuulaja ja sellele edastatud tagasihelistamise ära jätta, kuid siis tuleks skriptifail asetada keha HTML-i elemendi lõppu, et veenduda DOM-i täielikus laadimises, kui javascripti käivitamine algab. Kui valite nii, siis tehke seda julgelt. See on lihtsalt minu eelistatud viis seda teha, eeliseks on see, et see sisaldab ka kogu JavaScripti koodi funktsiooni ja väldib ülemaailmset reostust.

Peamiste sündmuste kuulamine

Järgmine samm oleks tuvastada, millal kasutaja klahvi vajutab. Teeme seda samamoodi, nagu lisasime DOMContentLoaded sündmuse kuulaja, kuid nüüd täpsustame erineva sündmuse nime. Klaviatuuri sündmusi, mida saame määratleda, on kolm: klahvivajutus, klahvivajutus ja klahvivajutus.

  • klahvivajutus - käivitub kohe klahvi vajutamisel
  • klaviatuur - vallandub klahvi vabastamisel
  • klahvivajutus - vallandub pidevalt, kuni klahvi hoitakse all

Sellest kirjeldusest näeme kohe, et klahvivajutus ei sobi meie eesmärgi saavutamiseks kindlasti. See jätab meile klahvid ja klahvid. Meie puhul lähevad mõlemad need hästi hakkama, kuid erinevas olukorras võib üks neist sobivam olla kui teine, seega peate olukorda hindama ja vastavalt valima.

Ainus erinevus, mida siin võime märgata, on see, et klaviatuuri kasutamisel võib see tunduda pisut aeglane, samal ajal kui klahvivajutamine tunneb reaktsiooni kohe. Valin klahvivajutuse, kuid kuna sama on võimalik saavutada klaviatuuriga, kasutage julgelt üritust, mis teile rohkem meeldib.

Lisame nüüd sündmuse kuulaja ja eemaldame konsoolilogi:

Siin tuleb tähele panna kahte olulist asja. Esiteks oleme lisamise sündmuse nime lisanud rakendusele addEventListener ja edastame sündmuse käitleja tagasihelistamise funktsiooni sündmuse parameetri. Vajame seda sündmuse parameetrit, et kontrollida, millist klahvi vajutatakse.

Niisiis, vajutatud võtme saamiseks pääseme juurde sündmuse objekti võtmeomadustele:

Vihje: sündmuse objekti saadaolevate omaduste nägemiseks tehke lihtsalt console.log (event) ja vaadake logitud objekti. Ma tean, et see võib tunduda ilmne, kuid kui olete algaja, võite proovida saadaolevaid valikuid veebist otsida, mis on küll hea, kuid vastus on tavaliselt vaid konsoolilogi eemal.

Pärast sündmuse.key saamist muudame selle väiketähtedeks, sest oleks hea muuta need klaviatuuri otseteed tundmatuks. Iga kord ei juhtu, kuid seekord on see täiesti korras.

Kui avate brauseri konsooli, klõpsate lehel tagasi ja proovite midagi trükkida, näete, et klahv, mida vajutasite, logitakse konsooli. Kuid kui olete tähelepanelik, võite märgata, et see logib mis tahes vajutatud klahvi, logitakse ka sellised klahvid nagu Enter, Kustuta, Backspace jne. See on suurepärane ja võib olla kasulik, kuid sel juhul tahan kasutada ainult tähti ja numbreid.

Seetõttu lisame kontrolli, kas vajutatav võti on täht või number.

Luues muutuja charList, mis sisaldab kõiki meid huvitavaid märke, saame kontrollida, kas võti on charListi stringis, ja kui ei, siis naaseme funktsioonist lihtsalt ilma tähemärki logimata.

Nüüd, kui kuulame võtmesündmusi ja suudame filtreerida ainult meid huvitavaid klahve, on aeg vaadata, kuidas saaksime sisestatud klahvide jada salvestada.

Sisestatud klahvijada salvestamine

Sisestatud klahvide jada salvestamiseks peame lisama muutuja, mis salvestab selle jada ja mida saame värskendada iga meid huvitava võtmesündmuse korral.

Võiksime kasutada stringi, millel saaksime võtmeid siduda, kuid võime kasutada ka massiivi, milles saame massiivi üksustena salvestada üksikuid võtmeid. Sel lihtsal kasutamisel pole vahet, mida me kasutame, aga ma ei lähe massiivi lähenemisviisi juurde.

Massiivipõhine lähenemisviis on stringi liitmise kohta soovitatav lähenemisviis juhul, kui palju stringe tuleb siduda, ning see võimaldab meil kasutada kõiki massiivi meetodeid, kui me neid vajame.

Loome muutuja, mida nimetatakse puhver, algul tühi massiiv ja lükake uued võtmed selle sisse.

Kui määratleme puhvermassiivi klahvide allalaadimise sündmuse kuulajas, lähtestatakse see iga klahvi vajutamisel ja sisestatud klahvide jaotus kaob. Seetõttu peame selle määratlema väljaspool võtmesõidu kuulajat. Nüüd on meil võimalik salvestada kõik sisestatud klahvid.

Kui logi vaatame, võime märgata, et nüüd salvestame võtmeid kogu aeg ja massiiv kasvab lihtsalt uute klahvide vajutamisega. Tulemuse nägemiseks kontrollige gif-lõõtsa.

Lisame pidevalt puhvermassiivi klahvivajutusi

Vaadake, kuidas pärast 'tere' kirjutamist ja mõningast viivitust, kui ma jätkan tippimist, on massiivis endiselt kõik eelnevad väärtused. See ei ole väga kasulik selleks, mida me tahame. Hea oleks sisestatud klahvide loend lähtestada pärast seda, kui on möödunud kindel aeg pärast viimase klahvi sisestamist.

Selle tingimuse täitmiseks võime kasutada ajavahemikku kahe viimase klahvivajutuse vahel. Kui see intervall on pikem kui määratud aeg, lähtestame puhvermassiivi. Teeme seda järgmisena.

Piirake klahvivajutuste vahelist ajavahemikku

Selleks peame võrdlema, millal juhtus viimane ja praegune klahvivajutus, ja seejärel kontrollima, kas nende vaheline aeg oli suurem kui mõni soovitud viivitus, näiteks 1 sekund, 0,5 sekundit, olenemata sellest, mis teile kõige mugavam on.

Niisiis, viimase klahvivajutuse aja säästmiseks peab meil olema vähemalt üks uus muutuja. Selle väärtuse kontrollimiseks peame muutuja määratlema väljaspool sündmuse kuulajat ja värskendama seda pärast klahvivajutuse toimumist.

Tutvustasime kahte uut muutujat, lastKeyTime ja currentTime. Me saame seda teha ainult lastKeyTime'iga, kuid praeguse timeTime'i muutujaga on seda palju lihtsam põhjendada. Vaatame, mida me siin tegime.

Esiteks määratlesime muutuja lastKeyTime ja lähtesime selle praeguse ajaväärtusega. Pidime selle initsialiseerima, kuna arvutamise lõõtsa teostamiseks on vaja mingit väärtust. Võime siin väärtusena kasutada nulli, kuid järjepidevuse huvides kasutame praegust ajaväärtust.

Järgmisena määratlesime muutuja currentTime ja lähtestame selle ka praeguse kellaajaga. Sel hetkel võib keegi küsida, miks kaks muutujat, millel on sama väärtus?! Pidage meeles, et need on lihtsalt initsialiseerimisväärtused, vähemalt lastKeyTime jaoks. Peame seda väärtust värskendama pärast iga klahvivajutust. Ja pange tähele, et lastKeyTime lähtestatakse väljaspool sündmuse kuulajat, see tähendab ainult üks kord, samas kui currentTime taasalustatakse igal klahvivajutusel.

Nüüd on meil oluline osa - kontrollida, kas klahvivajutuste vahel on piisavalt aega möödunud. Kui see on olemas, tahame lähtestada puhvermuutuja - massiivi, mis sisaldab tähemärke, mille kasutaja on vajutanud.

Selle kontrollimiseks lahutame lihtsalt muutuja currentTime viimaseKeyTime ja kontrollime, kas tulemus on suurem kui mõni arv. Näites on see arv 1000, see tähendab 1000 millisekundit või 1 sekund. See on hea lähteväärtus ja seda saab kogemuste paremaks häälestamiseks hiljem muuta.

Niisiis, kui tingimus currentTime - lastKeyTime> 1000 on tõene, lähtestame puhvri tühjale massiivile: puhver = []; Pärast seda saab puhver uue võtme, kuid see on massiivis ainus.

Viimane asi, mida peame siin tegema, on väärtuse lastKeyTime värskendamine. Me lihtsalt määrasime selle väärtuse samaks, mis praeguse aja väärtus. Järgmisel klahvivajutusel hoiab lastKeyTime aega, millal viimane klahvivajutus juhtus, kuni praeguneTime saab uue väärtuse.

Taustapildi värskendamine

Lõpuks oleme valmis tegema seda, mida soovisime, muuta tausta vastavalt kasutaja sisestatud klahvide järjestusele.

Kui kasutaja sisestab õige võtmejada, peame haarama elemendi lehel ja värskendama selle tausta vastavalt kasutaja sisendile. Tundub, et peame kontrollima, kas klahvide õige jada on õige.

Ehkki see on enamikul juhtudel peaaegu kindlasti tõsi, pole käesoleval juhul seda vaja. Selle probleemi olemus võimaldab meil vahele jätta kontrolli, kas meil on kõik korras, mis juhtub siis, kui võtmejada pole õige.

Mida ma selle all mõtlen? Las ma selgitan üksikasjalikult.

Kui tahame CSS-i abil taustpilti muuta, peame värskendama pildi URL-i. Kui piltide nimi on sama kui klahvijadadel, siis peame vaid lugema sisendi, muutma selle stringi ja määrama selle taustpildi URL-iks.

Huvitav on see, et kui pilti pole olemas, siis tausta ei näidata. Mis tähendab, et kui kuvatakse pilt ja sisestate midagi, mis ei vasta olemasolevale URL-ile, siis taustpilt puudub.

Sel juhul on mul kõik sellega korras, seetõttu pole vaja kontrollida, kas URL on õige. Kuid kui me tahaksime praegu kuvatavat pilti säilitada, on see kontroll vajalik. Tehkem seda lihtsal viisil, st ilma selle kontrollita.

Oleme eemaldanud console.log ja lisanud selle asemel päringu, et saada element, millel taust kuvatakse, ja järgmisel real rakendame tausta URL-i.

See URL-i struktuur sõltub teie projekti struktuurist; sel juhul on pildid kaustas 'images' ja need on JPG-vormingus. Oluline on siinjuures tähele panna, et meil tuleb puhvermassiivist luua string, et seda saaks kasutada pildi URL-is. Teeme seda, liites lihtsalt massiivi elemendid tühja tähemärgiga liitumismärgiks, buffer.join ('').

Sellega oleme saavutanud selle artikli peamise eesmärgi. Nüüd saab kasutaja proovida sisestada õige võtmejada ja kui see õnnestub, muutub taust. See, mida oleme teinud, on lihtne ja funktsionaalne ning hõlpsasti integreeritav igasse projekti.

Kuid mõned parandused on siiski võimalik. Seega, kui teile meeldib oma koodis paindlikum olla, lugege edasi.

Projekti täiustamine

Meie koodi tervikuna vaatamine näitab, et me kasutame mõnda globaalset muutujat. Globaalne selles mõttes, et nad asuvad meie skripti ülemises kontekstis, mis on suletud DOMContentLoaded sündmuste kuulaja funktsiooni, kus kogu ülejäänud kood asub, mis tähendab, et nad segunevad muude skripti tipptasemel muutujatega.

Kuid muutujate puhver ja lastKeyTime ei saa deklareerida klahvivajutuse sündmuse kuulajas, sest see lähtestab need iga klahvivajutusega ja rikub funktsionaalsuse.

Kood mähitakse funktsiooni

Meie põhisündmusi kontrolliva koodi eraldamiseks võime muutujad ja võtmeülesannete kuulaja eraldi funktsiooni panna.

Sellega on meie keyMapperi funktsioon täiesti sõltumatu muudest skripti koodidest ja selle saab veelgi selgemaks muutmiseks importida teisest failist. Kuid nüüd, kui see funktsioon meil on, näeme ka muid võimalusi paremaks muutmiseks.

Kõvakodeeritud väärtuste eemaldamine

Üks olulisemaid funktsioone, mida funktsiooni paindlikumaks muutmiseks teha saame, on eemaldada kõik kõvakodeeritud väärtused, mida me kasutame, ja anda need funktsioonile parameetritena.

Kõige olulisemad kõvakodeeritud väärtused on taustmahuti elemendi valija (#background), pildi URL-i osad ja ajaline viivitus selle kontrollimisel, kui (currentTime - lastKeyTime> 1000). Seal on ka muutuja charList, kuid ehkki võime seda ka parameetrina edastada ja juhtida täpselt, millised märgid on lubatud, võime selle praegu lihtsamaks muuta.

Selle asemel, mida me charListiga teha saame, on teisaldada see sündmuse kuulajast välja funktsiooni keyMapper, et vältida selle kuulutamist igal klahvivajutusel. Teeme siis kõik need muudatused.

Nüüd võtab keyMapper funktsioon neli parameetrit, mis võimaldavad meil seda hõlpsamini kohandada. Nüüd, kui funktsioonil on rohkem kui kolm parameetrit, hakkab see tunduma pisut kohmakas, on seda kerge unustada või segada. Parandame selle natuke hiljem, kuid nüüd jätkame sellega.

Looge tagasihelistamise funktsioon

Meie skripti soovitud toiming on lehe elemendi tausta värskendamine. See juhtub skripti viimasel real. Kuid võib-olla soovite, et pärast konkreetse klahvijada sisestamist juhtuks midagi täiesti teistsugust, võib-olla mängida heli, avada dialoog või mis iganes te võite mõelda.

Skripti praeguses versioonis saame värskendada ainult tausta. Kuid oleks väga tore, kui saaksime oma skripti hõlpsalt öelda, kui soovime selle asemel midagi muud teha, st kasutada funktsiooni keyMapper, et saaksime täita meie määratletud funktsiooni. Selleks saame määratleda funktsiooni, mille saame üle anda funktsioonile keyMapper ja seejärel seda sealt täita.

Nagu näete, aktsepteerib uus funktsioon keyMapper veel ühe parameetri (dooh!), Tagasihelistamise, mis on funktsioon, mida soovime pärast klahvi vajutamist täita. Funktsiooni keyMapper sees viimasel real kutsume seda tagasihelistamise funktsiooni ja anname sellele mõned muutujad, mida ta vajab. Kui KeyMapper kutsutakse, andsime sellele edasi funktsiooni updateBackground, mis kuulutatakse välja pärast keyMapper funktsiooni.

Funktsiooni värskendusBackground sisaldab põhimõtteliselt neid kahte viimast rida KeyMapperist, mille oleme eemaldanud. Sellega eraldasime võtmejada salvestamise täielikult ja toiming, mis tehakse pärast selle jada saamist.

Kui kirjutaksime uue funktsiooni ja edastaksime selle tagasiukutsumisele keyMapperile funktsiooni updateBackground asemel, võime saada hoopis teistsuguse käitumise.

Samm tagasi

Üks asi, mis mind palju häirima hakkas, on asjaolu, et meil on nüüd viis funktsiooni keyMapper ja neli funktsiooni updateBackground parameetreid ning kõik updateBackgroundi parameetrid edastatakse ka funktsioonile keyMapper enne nende edastamist updateBackground funktsioon.

Nüüd, kui oleme tagasihelistamise funktsiooni funktsioonist keyMapper eraldanud, on mõttekas värskendada funktsiooni updateBackground nõutavad väärtused lihtsalt kõvakodeerimisega, kuna sellisel viisil sisaldame kogu tagasihelistamise funktsioonis vajalikku teavet ja saame sellele helistada ainult ühe parameetriga. , võtmejada, mida keyMapper pakub.

See tähendab ka, et funktsiooni keyMapper saab kutsuda ainult kahe parameetriga, klahvivajutusDelay ja tagasihelistamise funktsiooniga. Siin on värskendatud skript:

Nüüd näeb see pisut puhtam välja ja funktsioonid ning parameetrid on kenasti eraldatud.

Sellegipoolest saame natuke paremini hakkama.

Võib-olla olete märganud, et funktsioonis keyMapper on veel üks kõvakodeeritud string - võtme mahakandmise sündmuse nimi. Kui me otsustaksime, et keyMapper töötab selle asemel klaviatuuri sündmusel, peaksime seda muutma otse funktsiooni sees. See pole tingimata suur probleem, kuid oleks tore, kui saaksime ka neid minimaalseid parameetreid kontrollida.

Niisiis, lisame funktsiooni keyMapper kolmanda parameetri?

Me võiksime seda teha, kuid lähme sammu edasi ja teeme sellest vaid ühe parameetri. Tutvustame ...

Valikute objekt

Tõeliselt kena viis funktsioonide parameetrite pakkumiseks on anda objektile omadused, millel on parameetri väärtused. See on kõige kasulikum juhtudel, kui funktsioonile tuleb anda palju parameetreid, eriti kui need parameetrid on valikulised ja esindavad funktsiooni mingisugust konfiguratsiooni.

Parameetrid, mida vajame funktsiooni keyMapper, keystrokeDelay ja uue eventType lisamiseks, näevad tõesti välja nagu konfiguratsiooniväärtused. Objekti parameetrite funktsioonile edastamiseks kasutamise eeliseks on see, et parameetrite järjekord ei oma tähtsust.

Nüüd saame seda teha nii:

Suvandobjekt sisaldab nüüd kuulatava sündmuse nime ja klahvivajutuste vahelist viivitust. Funktsioonis keyMapper on meil ka kaks rida:

const eventType = options && options.eventType || 'klahvivajutus';
const keystrokeDelay = options && options.keystrokeDelay || 1000;

Siin tegime oma parameetrid valikuliseks. Kui väärtused pakutakse läbi suvandiobjekti, kasutatakse neid, kui mitte, siis kasutame vaikeväärtusi. Saate seda testida, muutes suvandiobjekti väärtusi. Funktsiooni keyMapper üleskutses võite suvandobjekti täielikult ära jätta ja see töötab endiselt vaikimisi väärtustega.

Saame tagasihelistamise funktsiooni edastada ka läbi optsiooniobjekti, kuid kuna ilma selle funktsioonita poleks meil mõistlikku funktsionaalsust, tundub parem edastada see eraldi ja vajaliku parameetrina.

Veel tuleb selles viimases muudatuses tähele panna, et funktsiooni keyMapper parameetrite järjekord on vastupidine. Seda ei olnud vaja teha, kuid kui parameeter on valikuline, pakutakse seda tavaliselt pärast nõutavaid, vastasel juhul, kui soovite valikuliste parameetrite parameetri ära jätta, peate kutsuma funktsiooni keyMapper järgmiselt:

keyMapper (null, updateBackground); // null on suvandiobjekti väärtus

Lisage riigi juhtimine

Ei, see ei ole redux ega mõni muu riigihaldusraamatukogu, oleks rumal lisada kogu väikese raamatukogu jaoks kogu kogu. Korraldame lihtsalt muutujad, mis hoiavad skripti olekut, puhver- ja lastKeyTime, ühte objekti ja värskendame seda iga muudatuse korral.

Nüüd salvestatakse võtmejada ja viimase klahvivajutuse aeg olekuobjekti puhver- ja viimaseKeyTime atribuudina. Igal klahvivajutusel kopeerime puhvri omaduse kohalikku puhvermuutujasse ja värskendame seda vastavalt.

Pärast seda värskendatakse olekut kohaliku puhvermuutuja ja praeguse aja muutujaga. Lõpus helistatakse tagasihelistamisele praeguse puhverväärtusega.

Siinkohal tuleb märkida, et me ei uuenda kunagi olemasolevat olekuobjekti ega selle puhveromadusi, vaid loome alati olekule uue objekti ja puhverpildi jaoks uue massiivi. Seda nimetatakse oleku muutumatuks värskenduseks ja see on eelistatud oleku värskendamise viis. Me ei muuda kunagi eelmist väärtust / objekti, määrame uue väärtuse / objekti alati olekule.

Rida: puhver = [võti]; lähtestab puhvri juhul, kui klahvivajutuste vahel on möödunud rohkem aega, kui klahvivajutusDelay määratleb.

Rida puhver = [… oleku puhver, võti]; kasutab hajutamisoperaatorit ... uue massiivi täitmiseks olekupuhvri väärtustega ja siis lisame massiivi praeguse võtme. Sellega puhver värskendatakse.

Lõpuks rea olek = {puhver: puhver, lastKeyTime: currentTime}; värskendab olekut, määrates uuele objektile uued puhver- ja lastKeyTime väärtused.

Selles viimases koodinäidises eemaldasin märkide testi, kuna see ei paranda skripti funktsionaalsust, kuid muidugi saate skripti käitumise kontrollimiseks alati lisada ka oma kontrolli.

Viimane puudutus

Meie skript on nüüd valmis. Saame seada valikuid, luua mis tahes soovitud tagasihelistamise funktsiooni, olekut värskendatakse muutumatult. Üldiselt on meie keyMapperi funktsioon nüüd üsna paindlik.

Kui uurite brauseri lehte lähemalt, märkate, et vasakul on see veerg, kus on veidi teavet. Veeru alumises osas näete kasutaja sisestatud võtmejada (“mõned võtmed”) ja kasutajale tagasisõnumi (“veel midagi”) kohahoidjaid. Need on praegu kasutud, kuid me saame seda lihtsalt muuta. Selleks on mitu viisi.

Lihtsaim viis on tagasihelistamisfunktsiooni updateBackground täiendava funktsionaalsuse lisamine. Kuid see muudab funktsiooni funktsiooni ja selle nime ei kirjeldata korralikult.

Niisiis, võime kirjutada oma uue koodi teise funktsiooni sisse ja kutsuda selle funktsiooni funktsiooni updateBackground alt. See ei ole ideaalne lahendus, kuid see on parem kui lihtsalt uue koodi lappimine, millel pole midagi pistmist tausta värskendamisega funktsiooni updateBackground. Nii toimiksime järgmiselt:

Teine viis selleks on lihtsalt KeyMapperi teistkordne helistamine, kasutades tagasihelistamise funktsiooni updateUI:

See on pisut parem, kui asi puudutab funktsionaalsuse eraldamist, kuid nüüd on meil kaks sündmuse kuulajat, kes põhimõtteliselt teevad sama asja.

Oleks hea, kui meil oleks võtmesündmuste jaoks ainult üks sündmusekuulaja ja helistaksime siis sündmuse toimumisel kõik funktsioonid, mida me soovime.

Ja me saame seda teha, peame vaid andma kõik need funktsioonid funktsioonile keyMapper ja parim viis selleks on massiivi edastamine, mis sisaldab viiteid kõigile tagasihelistamise funktsioonidele, mida me soovime võtmesündmuse toimumisel täita. Koodi värskendamine selle saavutamiseks on tõesti lihtne:

Funktsioon keyMapper võtab nüüd vastu funktsioonide viidete massiivi:

keyMapper ([updateBackground, updateUI], suvandid);

ja siis puhvervärskenduse korral kutsutakse kõiki neid funktsioone:

callbackList.forEach (tagasihelistamine => tagasihelistamine (puhver));

Uue funktsionaalsuse lisamine võtmesündmustele on nüüd sama lihtne kui funktsiooni kirjutamine, mis eelistab me soovitud, ja selle viite edastamine funktsioonile keyMapper, kui me seda kutsume.

UPDATE (21. veebruar 2019)

Kommentaarides tõsteti esile, et kasutaja saab sisestada tee nagu ../myimage ja mis pääseks juurde mõnele failile, mis asub kataloogistruktuuris ühel tasemel ... kui see on olemas. Vältimaks võimalust kasutada muid tähti kui tähti ja numbreid, lisatakse värskenduste funktsiooniBackgroundfunktsiooni järgmised read:

const validKeys = keySequence.every (võti =>! isNaN (parseInt (võti)) || key.toLowerCase ()! == key.toUpperCase ());
if (! kehtivad võtmed) tagasi;

Samuti tagastab funktsioon keyMapper võtmed, mida pole teisendatud väiketähtedeks. See muundamine toimub nüüd tagasihelistamisfunktsioonides, mis seda peavad tegema, nagu näiteks updateUIfunction.

UPDATE (15. veebruar 2019) - JavaScript ütleb, et see on tõene (0 == vale) ja see ('' == vale)

Pärast meeldetuletust kommentaarides tõestusväärtuste hindamise kasutamise ohtude kohta JavaScriptis otsustasin selle probleemiga tegeleda ja probleemi lahendada.

Küsimus on nendes ridades:

const eventType = options && options.eventType || 'klahvivajutus';
const keystrokeDelay = options && options.keystrokeDelay || 1000;

Nagu ma juba mainisin, kasutab see väärtust objektist options, kui see on olemas, ja kui seda pole, siis kasutab see vaikeväärtust. Välja arvatud see, et ta ei tee seda igal juhul. Kui mingil põhjusel on options.eventType ja options.keystrokeDelay väärtused, mille väärtus on vale, siis neid väärtusi ei kasutata ja see läheb vaikeseadete juurde.

Me eeldasime, et nende omaduste korral, kui neid pole, oleks määratlemata väärtus, mis osutub valeks ja kasutame siis vaikeseadeid. Väärtust null saab hinnata ka valeks, mis on ka ok.

Mida me siin pole kaalunud, on muutujate tüüp. Selle põhjuseks on asjaolu, et sõltuvalt muutuja tüübist võib meil esineda ka muid valesid väärtusi.

Eeldame, et esimene atribuut, options.eventType, on string. Aga mis siis, kui see on tühi nöör? Javascript ütleb, et tühi string peaks sellistes võrdlustes olema vale. Mis tähendab, et kui edastame atribuudile options.eventType tühja stringi, saame ikkagi vaikese võtmesurvesündmuse, kuna tühja stringi väärtus on vale. Kuid kui me midagi ei annaks, siis see ei töötaks! Niisiis, tegelikult töötab see meie kasuks, et ebaõnnestu stringi kontrollimisel ebaõnnestuda ja kasutada vaikeklahvi vaikesündmuse tüüpi. See on hea.

Teine omadus, options.keystrokeDelay, on eeldatavasti number. Ja numbrite puhul peaks JavaScript ütlema, et null peaks olema vale. Kui me tahaksime viivitusväärtuse jaoks nulli ületada, siis seda ei aktsepteerita ja see langeb tagasi vaikeväärtusele 1000 ms. Kuid teisest küljest kuulen teid ütlemas: "Kes võiks kirjutada nii kiiresti, et nullväärtust tuleks üldse arvestada?". Ja teil on õigus, sel juhul on see kõik mõttetu, saime kuulata ainult ühte klahvi korraga.

Nii et ka meil on siin hea, pole vaja midagi teha? Tegelikult mitte. Mis siis, kui esitatud arv on negatiivne? Kindlasti ei lähe see ajas tagasi ega reageeri klahvivajutustele enne nende ilmnemist, kuid teeb seda kohe, kui need ilmnevad. Põhimõtteliselt on see sama kui väärtuse nulli seadmine, kuid see läbib tõesuse testi. Nüüd näeme, et vajame siin veel ühte tingimust, vajame nullist suuremaid numbreid. Nüüd lahendasime probleemi, kuid mis juhtuks, kui keegi ületaks numbri nagu 10? Kas kahe klahvivajutuse ühendamiseks piisab 10msist? Mitte minu jaoks, see on kindel. Vaevalt saan sellega hakkama 250ms viivitusega. Minu kui selle rakenduse arendaja seisukohast ei näe ma põhjust lubada viivitusi, mis on väiksemad kui mul on vaja kahe klahvivajutuse ühendamiseks. Nii et olen otsustanud piirata viivituse minimaalselt 300 millisekundiga.

Funktsiooni keyMapper värskendatud kood on järgmine:

Lisasin funktsiooni hasProperty, mis kontrollib, kas objektil on atribuudid, ja alles pärast selle kontrolli läbimist saame jätkata järgmiste kontrollidega. Viite real saate näha ka options.keystrokeDelay> = 300 kontrolli, mis piirab viivituse 300 ms-ni.

Viimane asi, mida tahaksin mainida, on see, et neid probleeme, millest selles värskendatud jaotises räägin, saab kõigepealt vältida, kui kirjutame oma koodile vastavad testid. Näiteks võime hõlpsalt mõelda tühja stringi probleemidele, kui kaalume, milliseid võimalikke sisendeid funktsioon võiks saada omaduse eventType jaoks. Sama kehtib ka klahvivajutuse viivituse kohta, kui arvestada võimalike sisenditega, saame kiiresti aru, et nulli, negatiivide või isegi liiga väikeste numbrite kasutamine ei tööta hästi.

Järeldus

Ehkki konkreetsele võtmejadadele reageerimise põhifunktsioonid olid lühike ja lihtne ülesanne, tahtsin minna veel paar sammu edasi ja näidata, kuidas me saame tõesti funktsiooni, mis on paindlik, võimaldada meil natuke paremat kontrolli. Saavutasime selle, kui taasesitusfunktsioonide loend ja valikud esitasid funktsiooni keyMapper.

Kuid saate funktsiooni veelgi kohandatavamaks muuta, pakkudes rohkem suvandeid ja lisades koodi nende uute võimalustega seotud funktsiooni.

Sõltuvalt sellest, mida vajate, saate seda laiendada nii palju kui soovite. Muidugi olge seda tehes mõistlik, kuna soovite, et teie kood oleks loetav ja hõlpsasti põhjendatav.

Loodetavasti on see artikkel andnud teile ideid, kuidas seda oma projektides kasutada, ja jagage neid soovi korral kommentaarides.

Täname, et lugesite ja head uut aastat!