17 of 17 menu

Klaida dėl DOM elementų redagavimo funkcijos dubliravimo JavaScript

Tarkime, kad turime tam tikrą sąrašą:

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

Gaukime patį sąrašą ir jo elementus į atskirus kintamuosius:

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

Padarykime taip, kad mūsų sąrašo elementus būtų galima redaguoti atsirandančiu įvesties lauku:

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

Tarkime, kad dabar norime, kad į sąrašą galėtume pridėti naujų elementų. Tegul tam po sąrašu yra atitinkamas įvesties laukas:

<input id="adder">

Gaukime nuorodą į šį įvesties lauką į kintamąjį:

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

Padarykime taip, kad praradus fokusą įvesties lauke, į sąrašą būtų pridėtas naujas elementas su tekstu, paimtu iš mūsų įvesties lauko:

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

Tarkime, kad dabar norime, kad ir naujai pridėti elementai taip pat būtų redaguojami. Pats savaime jiems redagavimas neveiks, nes kai mes užkrovėme paspaudimo apdorotoją sąrašo elementams, šių elementų dar nebuvo.

Pažiūrėkime į galimus šios problemos sprendimo variantus.

Pirmasis sprendimas

Paprasčiausias sprendimas – pakartoti funkcijos func kodą, pririšant ją ir naujai sukurtiems elementams:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function func() { // čia mes kartojame kodą }); ul.append(li); });

Žinoma, šiame sprendime iš karto matome trūkumą – kartoji kodą yra neteisinga.

Antrasis sprendimas

Norint išspręsti dubliravimo problemą, logiška išimti funkciją func į išorę, paversdami ją 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); }

Čia mūsų ir laukia problema. Faktas yra tas, kad mūsų funkcija naudojo kintamąjį li, gautą iš išorinės apimties. Bet po funkcijos išėmimo šis kintamasis dabar nematomas!

Norint išspręsti problemą, perduosime mūsų li parametru:

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

Ir čia mūsų sprendimas sukuria dar vieną problemą. Faktas yra tas, kad negalima tiesiog perduoti parametro į įvykio apdorotoją:

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

Norint išspręsti šią problemą, tiesiog iškviečiame mūsų funkciją anoniminio apdorotojo viduje:

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

Ir analogiškai elgsimės kurdami naują sąrašo elementą:

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

Trečiasis sprendimas

Egzistuoja elegantiškesnis sprendimas. Galima tiesiog pasinaudoti delegavimu. Šiuo atveju problema su naujais sąrašo elementais tiesiog nekils:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // fiksuojame būtent paspaudimą ant li, ne ant įvesties lauko 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; }); } });

Šiuo atveju ciklas per sąrašo elementus mums apskritai ir nebereikės, o kodas naujam sąrašo elementui sukurti susitrauks iki tokio:

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