17 of 17 menu

Kļūda ar DOM elementu rediģēšanas funkcijas dublēšanu JavaScript

Pieņemsim, ka mums ir noteikts saraksts:

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

Iegūstam pašu sarakstu un tā punktus atsevišķos mainīgos:

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

Uztaisīsim tā, lai mūsu saraksta punktus varētu rediģēt ar parādāmu ievades lauku:

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

Pieņemsim, ka tagad mēs vēlamies, lai sarakstā varētu pievienot jaunus punktus. Lai to izdarītu, zem saraksta mums būs atbilstošs ievades lauks:

<input id="adder">

Iegūstam atsauci uz šo ievades lauku mainīgajā:

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

Uztaisīsim tā, lai zaudējot fokusu no ievades lauka, sarakstam pievienotos jauns punkts ar tekstu, kas ņemts no mūsu ievades lauka:

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

Pieņemsim, ka tagad mēs vēlamies, lai arī jaunpievienotie punkti tiktu rediģējami. Paši par sevi rediģēšana tiem nestrādās, jo, kad mēs pievienojām klikšķa notikumu apstrādi saraksta punktiem, šo punktu vēl nebija.

Apskatīsimies iespējamos šīs problēmas risinājuma variantus.

Pirmais risinājums

Vienkāršākais risinājums ir dubultot funkcijas func kodu, piesiet to arī jaunizveidotajiem punktiem:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; li.addEventListener('click', function func() { // šeit mēs dubultojam kodu }); ul.append(li); });

Protams, šajā risinājumā mēs uzreiz redzam trūkumu - koda dublēšana nav pareiza.

Otrais risinājums

Lai atrisinātu dublēšanas problēmu, loģiski ir iznest funkciju func ārā, padarot to par Function Declaration:

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

Šeit mūs sagaida problēma. Lieta ir tāda, ka mūsu funkcija izmantoja mainīgo li, kas iegūts no ārējās redzamības apgabala. Bet pēc funkcijas iznešanas ārā šis mainīgais vairs nav redzams!

Lai atrisinātu problēmu, mēs padodam mūsu li kā parametru:

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

Un šeit mūsu risinājums rada vēl vienu problēmu. Lieta ir tāda, ka nevar vienkārši tā padot parametru notikuma apstrādes funkcijai:

for (let li in lis) { li.addEventListener('click', func(li)); // nestrādā! }

Lai atrisinātu šo problēmu, vienkārši izsaucam mūsu funkciju anonīmas apstrādes funkcijas iekšienē:

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

Un līdzīgi rīkojamies veidojot jaunu saraksta punktu:

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

Trešais risinājums

Pastāv elegantāks risinājums. Var vienkārši izmantot deleģēšanu. Šajā gadījumā problēma ar jaunajiem saraksta punktiem vienkārši neradīsies:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // ķeram tieši klikšķi uz li, ne uz ievades lauku 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; }); } });

Šajā gadījumā cikls pa saraksta punktiem mums vispār nebūs vajadzīgs, un kods jauna saraksta punkta izveidošanai saīsināsies līdz šim:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Latviešu
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Mēs izmantojam sīkdatnes, lai nodrošinātu vietnes darbību, analīti un personalizāciju. Datu apstrāde notiek saskaņā ar Konfidencialitātes politiku.
pieņemt visus iestatīt noraidīt