Скривени кључ за динамичке веб интеракције

Када сам још учио конопце за развој веба, једно од изненађујућих и интригантних понашања на које сам наишао било је бујање догађаја. У почетку је изгледало необично, али када размислите о бујању догађаја, видећете да има толико смисла. Као веб програмер, сигурно ћете наићи на бујање догађаја. Дакле, шта је то што се дешава?

Да би корисницима пружио могућност интеракције са веб страницама, ЈаваСцрипт се ослања на догађаје. Догађај се односи на појаве или радње које се могу открити и на које се може реаговати кодом који напишете. Примери догађаја укључују кликове мишем, притиске тастера и подношење обрасца, између осталог.

ЈаваСцрипт користи слушаоце догађаја да открије догађаје и одговори на њих. Слушалац догађаја је функција која слуша или чека да се одређени догађај догоди на страници. На пример, догађај клика на дугме. Када слушалац догађаја открије догађај који слуша, он одговара извршавањем кода повезаног са догађајем. Цео овај процес хватања и реаговања на догађаје назива се руковање догађајима.

Сада, замислите да имамо три елемента на страници: див, спан и дугме. Елемент дугмета је угнежђен унутар елемента спан, а елемент спан је угнежђен у див. Илустрација овога је приказана у наставку:

Под претпоставком да сваки од ових елемената има слушалац догађаја који ослушкује догађај клика и штампа на конзоли када се кликне, шта се дешава када кликнете на дугме?

Да бисте ово сами тестирали, направите фасциклу и у њој направите ХТМЛ датотеку под називом индек.хтмл, ЦСС датотеку под називом стиле.цсс и ЈаваСцрипт датотеку која се зове апп.јс.

У ХТМЛ датотеку додајте следећи код:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>Event bubbling</title>
  <link rel="stylesheet" href="https://wilku.top/the-hidden-key-to-dynamic-web-interactions/style.css">
</head>

<body>
  <div>
    <span><button>Click Me!</button></span>
  </div>
  <script src="app.js"></script>
</body>

</html>

У ЦСС датотеци додајте следећи код да бисте стилизовали див и елемент спан.

div {
  border: 2px solid black;
  background-color: orange;
  padding: 30px;
  width: 400px;
}

span {
  display: inline-block;
  background-color: cyan;
  height: 100px;
  width: 200px;
  margin: 10px;
  padding: 20px;
  border: 2px solid black;
}

У ЈаваСцрипт датотеци додајте следећи код, који додаје слушаоце догађаја елементима див, спан и дугмета. Сви спискови догађаја ослушкују догађај клика.

const div = document.querySelector('div');
div.addEventListener('click', () => {
  console.log("You've clicked a div element")
})

const span = document.querySelector('span');
span.addEventListener('click', () => {
  console.log("You've clicked a span element")
})

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button")
})

Сада отворите ХТМЛ датотеку у претраживачу. Прегледајте страницу, а затим кликните на дугме на страници. Шта ти примећујеш? Резултат клика на дугме је приказан у наставку:

Кликом на дугме покреће слушалац догађаја који ослушкује догађај клика на дугме. Међутим, покрећу се и слушаоци догађаја на елементима спан и див. Зашто је то тако, питате се.

Кликом на дугме покреће се слушалац догађаја повезан са дугметом, који се штампа на конзоли. Међутим, пошто је дугме угнежђено унутар елемента спан, клик на дугме значи да технички, такође кликћемо на елемент спан, и стога се покреће његов слушалац догађаја.

  Додајте потпуне функције бирања у контролни центар [Jailbreak]

Пошто је елемент спан такође угнежђен унутар елемента див, клик на елемент спан такође значи да се кликне и на елемент див, и као резултат тога, његов слушалац догађаја се такође покреће. Ово је бујање догађаја.

Евент Бубблинг

Бубирање догађаја је процес којим се догађај који је покренут у угнежђеном скупу ХТМЛ елемената пропагира или избацује из унутрашњег елемента где је покренут и путује уз ДОМ стабло до основног елемента, покрећући све слушаоце догађаја који слушају тај догађај.

Слушачи догађаја се покрећу одређеним редоследом који одговара начину на који догађај пребацује или шири ДОМ стабло. Размотрите ДОМ стабло приказано у наставку, које представља структуру ХТМЛ-а који се користи у овом чланку.

Догађај клика који се појављује у ДОМ стаблу

ДОМ стабло приказује дугме, угнежђено унутар распона, које је угнежђено у див, које је угнежђено унутар тела, а тело је угнежђено унутар ХТМЛ елемента. Пошто су елементи угнежђени један унутар другог када кликнете на дугме, догађај клика ће покренути слушалац догађаја повезан са дугметом.

Међутим, пошто су елементи угнежђени, догађај ће се померити нагоре по ДОМ стаблу (буббле уп) до елемента спан, затим див, затим тело и на крају ХТМЛ елемент, покрећући све слушаоце догађаја који слушају догађај клика у том ред.

Због тога се извршава слушалац догађаја прикачен на елементе спан и див. Да смо имали слушаоце догађаја који ослушкују клик на тело и ХТМЛ елемент, они би такође били покренути.

ДОМ чвор у којем се дешава догађај назива се циљ. У нашем случају, пошто се клик дешава на дугме, елемент дугмета је циљ догађаја.

Како зауставити бујање догађаја

Да бисмо спречили догађај да се појави у ДОМ-у, користимо метод који се зове стопПропагатион() који је доступан на објекту догађаја. Размотрите пример кода у наставку, који смо користили да додамо слушалац догађаја елементу дугмета.

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button");
})

Код доводи до догађаја који се појављује у ДОМ стаблу када корисник кликне на дугме. Да бисмо спречили појаву мехурића догађаја, позивамо метод стопПропагатион() као што је приказано у наставку:

const button = document.querySelector('button');
button.addEventListener('click', (e) => {
  console.log("You've clicked a button");
  e.stopPropagation();
})

Руковалац догађаја је функција која се извршава када се кликне на дугме. Слушалац догађаја аутоматски прослеђује објекат догађаја руковаоцу догађаја. У нашем случају, овај објекат догађаја је представљен именом променљиве е, које се прослеђује као параметар у руковаоцу догађаја.

Овај објекат догађаја, е, садржи информације о догађају и такође нам даје приступ разним својствима и методама које се односе на догађаје. Један такав метод је стопПропагатион(), који се користи да спречи појављивање мехурића догађаја. Позивање стопПропагатион() у слушаоцу догађаја дугмета спречава догађај да се појави у ДОМ стаблу из елемента дугмета.

  Виртуелне собе са подацима: предности, употреба и алати

Резултат клика на дугме након додавања методе стопПропагатион() је приказан испод:

Користимо стопПропагатион() да спречимо да се догађај појави из елемента на коме га користимо. На пример, ако желимо да се догађај клика појави од дугмета до елемента спан, а не даље од ДОМ стабла, користили бисмо стопПропагатион() на слушаоцу догађаја спан.

Евент Цаптуринг

Снимање догађаја је супротно од бубњања догађаја. Приликом снимања догађаја, догађај се спушта од најудаљенијег елемента до циљног елемента као што је илустровано у наставку:

Кликните на догађај који се спушта до циљног елемента због снимања догађаја

На пример, у нашем случају, када кликнете на елемент дугмета, при снимању догађаја, слушаоци догађаја на елементу див ће бити први који ће се покренути. Следе слушаоци на елементу спан и коначно, слушаоци на циљном елементу ће се покренути.

Мехурићи догађаја су, међутим, подразумевани начин на који се догађаји пропагирају у моделу објеката документа (ДОМ). Да бисмо променили подразумевано понашање са пуштања у мехуриће на снимање догађаја, прослеђујемо трећи аргумент нашим слушаоцима догађаја да би снимање догађаја поставили на тачно. Ако не проследите трећи аргумент слушаоцима догађаја, снимање догађаја је подешено на нетачно.

Узмите у обзир слушаоца догађаја у наставку:

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
})

Пошто нема трећи аргумент, снимање је подешено на фалсе. Да бисмо подесили снимање на труе, преносимо трећи аргумент, логичку вредност труе, која поставља снимање на труе.

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, true)

Алтернативно, можете проследити објекат који поставља цаптуре на труе, као што је приказано у наставку:

div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, {capture: true})

Да бисте тестирали снимање догађаја, у своју ЈаваСцрипт датотеку додајте трећи аргумент свим слушаоцима догађаја као што је приказано:

const div = document.querySelector('div');
div.addEventListener('click', () => {
  console.log("You've clicked a div element")
}, true)

const span = document.querySelector('span');
span.addEventListener('click', (e) => {
  console.log("You've clicked a span element")
}, true)

const button = document.querySelector('button');
button.addEventListener('click', () => {
  console.log("You've clicked a button");
}, true)

Сада отворите свој претраживач и кликните на елемент дугмета. Требало би да добијете такав излаз:

Обратите пажњу на то да за разлику од бубњања догађаја, где је излаз са дугмета прво одштампан, у хватању догађаја, први излаз је из најудаљенијег елемента, див.

Бубирање догађаја и снимање догађаја су главни начини на које се догађаји пропагирају у ДОМ-у. Међутим, буђење догађаја је оно што се обично користи за пропагирање догађаја.

Делегација догађаја

Делегирање догађаја је образац дизајна где је један слушалац догађаја везан за заједнички родитељски елемент, на пример елемент <ул>, уместо да има слушаоце догађаја на сваком од подређених елемената. Догађаји на подређеним елементима затим се појављују до родитељског елемента, где њима рукује руковалац догађаја на родитељском елементу.

Стога, у случају када имамо родитељски елемент са подређеним елементима унутар њега, родитељском елементу додајемо само слушалац догађаја. Овај обрађивач догађаја ће управљати свим догађајима у подређеним елементима.

  Како спречити да ваше е-поруке одлазе у нежељену пошту у Гмаил-у

Можда се питате како ће родитељски елемент знати на који подређени елемент је кликнут. Као што је раније поменуто, слушалац догађаја прослеђује објекат догађаја руковаоцу догађаја. Овај објекат догађаја има методе и својства која нуде информације о одређеном догађају. Једно од својстава у објекту догађаја је циљно својство. Циљно својство указује на одређени ХТМЛ елемент где се догодио догађај.

На пример, ако имамо неуређену листу са ставкама листе и прикачимо ослушкивач догађаја елементу <ул> када се догађај деси на ставци листе, циљно својство у објекту догађаја ће указивати на одређену ставку листе где је догађај дошло.

Да бисте видели делегирање догађаја у акцији, додајте следећи ХТМЛ код у постојећу ХТМЛ датотеку:

<ul>
    <li>Toyota</li>
    <li>Subaru</li>
    <li>Honda</li>
    <li>Hyundai</li>
    <li>Chevrolet</li>
    <li>Kia</li>
  </ul>

Додајте следећи ЈаваСцрипт код да бисте користили делегирање догађаја за коришћење једног слушаоца догађаја на надређеном елементу за слушање догађаја у подређеним елементима:

const ul = document.querySelector('ul');
ul.addEventListener('click', (e) => {
  // target element
  targetElement = e.target
  // log out the content of the target element
  console.log(targetElement.textContent)
})

Сада отворите претраживач и кликните на било коју ставку на листи. Садржај елемента треба да буде одштампан на конзоли као што је приказано у наставку:

Користећи један слушалац догађаја, можемо руковати догађајима у свим подређеним елементима. Толико слушалаца догађаја на страници утиче на њен учинак, троши више меморије и доводи до спорог учитавања и приказивања страница.

Делегирање догађаја нам омогућава да избегнемо све ово минимизирањем броја слушалаца догађаја које треба да користимо на страници. Делегирање догађаја се ослања на бујање догађаја. Стога, можемо рећи да мехурићи догађаја могу помоћи у оптимизацији перформанси веб страница.

Савети за ефикасно руковање догађајима

Као програмер, када радите са догађајима у објектном моделу документа, размислите о коришћењу делегирања догађаја уместо да имате много слушалаца догађаја на елементима на вашој страници.

Када користите делегирање догађаја, не заборавите да приложите слушаоца догађаја најближем заједничком претку подређених елемената којима је потребно руковање догађајима. Ово помаже у оптимизацији појављивања мехурића догађаја и такође минимизира путању коју догађај мора да пређе пре него што се њиме обради.

Када рукујете догађајима, користите објекат догађаја који обезбеђује слушалац догађаја у своју корист. Објекат догађаја садржи својства као што је циљ, која су згодна при руковању догађајима.

Да бисте имали ефикасније веб локације, избегавајте прекомерну манипулацију ДОМ-ом. Догађаји који покрећу честе ДОМ манипулације могу негативно утицати на учинак ваше веб локације.

Коначно, у случају угнежђених елемената, будите веома опрезни када елементима прилажете угнежђене слушаоце догађаја. Ово не само да може да утиче на перформансе, већ ће руковање догађајима учинити веома сложеним, а ваш код ће бити тешко одржавати.

Закључак

Догађаји су моћан алат у ЈаваСцрипт-у. Објашњење догађаја, снимање догађаја и делегирање догађаја су важни алати за руковање догађајима у ЈаваСцрипт-у. Као веб програмер, користите чланак да бисте се упознали са концептима како бисте могли да направите интерактивније, динамичније и ефикасније веб локације и апликације.