17 of 17 menu

Napaka podvajanja funkcije za urejanje DOM elementov v JavaScript

Recimo, da imamo nek seznam:

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

Pridobimo seznam in njegove elemente v ločene spremenljivke:

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

Naredimo tako, da lahko elemente našega seznama urejamo z vnosnim poljem, ki se prikaže:

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

Recimo sedaj, da želimo v seznam dodajati nove elemente. Naj bo za to pod seznamom ustrezno vnosno polje:

<input id="adder">

Pridobimo referenco na to vnosno polje v spremenljivko:

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

Naredimo tako, da ob izgubi fokusa vnosnega polja v seznam doda nov element z besedilom, vzetim iz našega vnosnega polja:

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

Recimo sedaj, da želimo, da lahko tudi na novo dodane elemente urejamo. Samo po sebi zanje urejanje ne bo delovalo, ker ko smo dodajali obravnavalnik klikov na elemente seznama, teh elementov še ni bilo.

Poglejmo si možne variante rešitve te težave.

Prva rešitev

Najenostavnejša rešitev je podvajanje kode funkcije func, jo povezati tudi za na novo ustvarjene elemente:

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

Seveda v tej rešitvi takoj vidimo pomanjkljivost - podvajati kodo ni pravilno.

Druga rešitev

Za rešitev težave podvajanja je logično postaviti funkcijo func ven, in jo narediti kot 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); }

Tu nas čaka težava. Bistvo je v tem, da je naša funkcija uporabljala spremenljivko li, pridobljeno iz zunanjega obsega vidnosti. Toda po premikanju funkcije ta spremenljivka zdaj ni več vidna!

Za rešitev težave bomo posredovali našo li kot parameter:

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

In tu naša rešitev povzroči še eno težavo. Bistvo je v tem, da ne moremo preprosto posredovati parametra v obravnavalnik dogodka:

for (let li of lis) { li.addEventListener('click', func(li)); // ne deluje! }

Za rešitev te težave preprosto pokličimo našo funkcijo znotraj anonimnega obravnavalnika:

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

In na enak način ravnamo pri ustvarjanju novega elementa seznama:

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

Tretja rešitev

Obstaja bolj elegantna rešitev. Lahko preprosto uporabimo delegiranje. V tem primeru se težava z novimi elementi seznama preprosto ne pojavi:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // ujamemo točno klik na li, ne na vnosno polje 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; }); } });

V tem primeru zanka po elementih seznama na sploh ne bo potrebna, in koda za ustvarjanje novega elementa seznama se skrajša na tole:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Slovenščina
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Za delovanje spletnega mesta, analitiko in personalizacijo uporabljamo piškotke. Obdelava podatkov poteka v skladu s Politiko zasebnosti.
sprejmi vse nastavi zavrni