17 of 17 menu

Eroare de duplicare a funcției de editare a elementelor DOM în JavaScript

Să presupunem că avem o listă:

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

Să obținem lista în sine și elementele sale în variabile separate:

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

Să facem astfel încât elementele listei noastre să poată fi editate printr-un câmp de introducere care apare:

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

Să presupunem acum că vrem să putem adăuga elemente noi în listă. Să presupunem că pentru aceasta avem un câmp de introducere corespunzător sub listă:

<input id="adder">

Să obținem o referință la acest câmp de introducere într-o variabilă:

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

Să facem astfel încât la pierderea focusului câmpului de introducere în listă să fie adăugat un nou element cu textul preluat din câmpul nostru de introducere:

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

Să presupunem acum că vrem ca și elementele nou adăugate să poată fi de asemenea editate. În sine, editarea pentru ele nu va funcționa automat, deoarece atunci când am atașat handler-ul de click pe elementele listei, aceste elemente nu existau încă.

Să ne uităm la posibilele variante de rezolvare a acestei probleme.

Soluția prima

Cea mai simplă soluție - este să duplicăm codul funcției func, atașând-o și pentru elementele nou create:

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

Desigur, în această soluție vedem imediat un dezavantaj - duplicarea codului nu este corectă.

Soluția a doua

Pentru a rezolva problema duplicării este logic să scoatem funcția func în afară, făcând-o o Declarație de Funcție (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); }

Aici ne așteaptă problema. Faptul este că funcția noastră folosea variabila li, obținută din domeniul de vizibilitate extern. Dar după scoaterea funcției, această variabilă nu mai este vizibilă!

Pentru a rezolva problema, vom transmite li-ul nostru ca 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); }

Și aici soluția noastră generează încă o problemă. Faptul este că nu se poate transmite pur și simplu un parametru într-un handler de eveniment:

for (let li of lis) { li.addEventListener('click', func(li)); // nu funcționează! }

Pentru a rezolva această problemă, pur și simplu apelăm funcția noastră în interiorul unui handler anonim:

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

Și în mod similar procedăm la crearea unui nou element de listă:

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

Soluția a treia

Există o soluție mai elegantă. Se poate pur și simplu folosi delegarea (delegation). În acest caz problema cu elementele noi ale listei pur și simplu nu va apărea:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // prindem tocmai click-ul pe li, nu pe 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; }); } });

În acest caz bucla pentru elementele listei nici nu va mai fi necesară, iar codul pentru crearea unui nou element de listă se va reduce la asta:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Română
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Folosim cookie pentru funcționarea site-ului, analiză și personalizare. Prelucrarea datelor are loc în conformitate cu Politica de confidențialitate.
acceptă toate configurează respinge