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');

Да направиме ставките од нашата листа да бидат уредливи преку инпут кој се појавува:

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 id="adder">

Да ја добиеме референцата кон овој инпут во променлива:

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

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

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, не на инпут 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šuMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Ние користиме колачиња за работата на веб-страната, анализа и персонализација. Обработката на податоци се врши во согласност со Политиката за приватност.
прифати ги сите прилагоди одбиј