17 of 17 menu

Грешка дуплирања функције за уређивање DOM елемената у JavaScript-у

Претпоставимо да имамо следећу листу:

<ul> <li>1</li> <li>2</li> <li>3</li> </ul>

Дохватимо саму листу и њене ставке у засебне променљиве:

let ul = document.querySelector('ul'); let lis = document.querySelectorAll('li');

Омогућимо да се ставке наше листе могу уређивати помоћу input поља које се појављује:

for (let li of lis) { li.addEventListener('click', function func() { let input = document.createElement('input'); input.value = li.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }); }

Претпоставимо сада да желимо да у листу можемо додавати нове ставке. Зато нека испод листе имамо одговарајуће input поље:

<input id="adder">

Дохватимо референцу на ово input поље у променљиву:

let adder = document.querySelector('#adder');

Омогућимо да при губитку фокуса са input поља у листу буде додата нова ставка са текстом, преузетим из нашег input поља:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });

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

Погледајмо могуће варијанте решења овог проблема.

Прво решење

Најједноставније решење је да дуплирамо код функције func, прикачивши је и за новокреиране ставке:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function func() { // овде дуплирамо код }); ul.append(li); });

Наравно, у овом решењу одмах видимо недостатак - дуплирање кода није исправно.

Друго решење

Да би решили проблем дуплирања логично је да функцију func извадимо напоље, направивши је Function Declaration:

function func() { let input = document.createElement('input'); input.value = li.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }

Ту нас и чека проблем. Ствар је у томе што је наша функција користила променљиву li, добијену из спољашњег опсега видљивости. Али након извлачења функције та променљива сада није видљива!

Да решимо проблем, проследићемо нашу li као параметар:

function func(li) { let input = document.createElement('input'); input.value = li.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; li.addEventListener('click', func); }); li.removeEventListener('click', func); }

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

for (let li of lis) { li.addEventListener('click', func(li)); // не ради! }

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

for (let li of lis) { li.addEventListener('click', function() { func(li); }); }

И на сличан начин ћемо поступити при креирању нове ставке листе:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function() { func(li); }); ul.append(li); });

Треће решење

Постоји елегантније решење. Можемо једноставно искористити делегирање догађаја. У том случају проблем са новим ставкама листе једноставно неће настати:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // хватамо баш клик на li, не на input let li = event.target; let input = document.createElement('input'); input.value = li.textContent; li.textContent = ''; li.append(input); input.addEventListener('blur', function() { li.textContent = this.value; }); } });

У овом случају петља кроз ставке листе нам уопште неће бити потребна, а код за креирање нове ставке листе ће се свести на ово:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Српски
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Користимо колачиће за рад сајта, аналитику и персонализацију. Обрада података се врши у складу са Политиком приватности.
прихвати све подеси одбиј