17 of 17 menu

Fehler bei der Duplizierung der DOM-Element-Bearbeitungsfunktion in JavaScript

Nehmen wir an, wir haben eine bestimmte Liste:

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

Wir holen die Liste selbst und ihre Punkte in separate Variablen:

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

Sorgen wir dafür, dass die Punkte unserer Liste mit einem erscheinenden Input-Feld bearbeitet werden können:

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

Nehmen wir nun an, wir möchten, dass der Liste neue Punkte hinzugefügt werden können. Dafür soll unter der Liste ein entsprechendes Input-Feld sein:

<input id="adder">

Wir holen eine Referenz auf dieses Input-Feld in eine Variable:

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

Sorgen wir dafür, dass beim Verlust des Fokus des Input-Felds in die Liste ein neuer Punkt mit dem Text hinzugefügt wird, der aus unserem Input-Feld entnommen wurde:

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

Nehmen wir nun an, wir möchten, dass auch die neu hinzugefügten Punkte bearbeitet werden können. Von selbst wird das Bearbeiten für sie nicht funktionieren, denn als wir den Event-Handler für den Klick auf die Listenelemente gesetzt haben, existierten diese Punkte noch nicht.

Schauen wir uns die möglichen Lösungsansätze für dieses Problem an.

Erste Lösung

Die einfachste Lösung ist, den Code der Funktion func zu duplizieren und sie auch für die neu erstellten Punkte zu binden:

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

Natürlich sehen wir in dieser Lösung sofort einen Nachteil - Code zu duplizieren ist nicht richtig.

Zweite Lösung

Um das Problem der Duplizierung zu lösen, ist es logisch, die Funktion func nach außen zu ziehen und sie zu einer Function Declaration zu machen:

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

Hier lauert das Problem auf uns. Die Sache ist die, dass unsere Funktion die Variable li verwendet hat, die vom äußeren Gültigkeitsbereich bezogen wurde. Aber nachdem die Funktion herausgezogen wurde, ist diese Variable nun nicht mehr sichtbar!

Um das Problem zu lösen, werden wir unsere li als Parameter übergeben:

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

Und hier erzeugt unsere Lösung noch ein weiteres Problem. Die Sache ist die, dass man nicht einfach so einen Parameter an einen Event-Handler übergeben kann:

for (let li in lis) { li.addEventListener('click', func(li)); // funktioniert nicht! }

Um dieses Problem zu lösen, rufen wir einfach unsere Funktion innerhalb eines anonymen Handlers auf:

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

Und genauso verfahren wir beim Erstellen eines neuen Listenelements:

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

Dritte Lösung

Es gibt eine elegantere Lösung. Man kann einfach Event-Delegation nutzen. In diesem Fall wird das Problem mit neuen Listenelementen einfach nicht auftreten:

ul.addEventListener('click', function(event) { if (event.target.tagName === 'LI') { // fangen genau den Klick auf li ab, nicht auf 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; }); } });

In diesem Fall wird die Schleife über die Listenelemente generell nicht nötig sein, und der Code für die Erstellung eines neuen Listenelements kürzt sich auf Folgendes:

adder.addEventListener('blur', function() { let li = document.createElement('li'); li.textContent = this.value; ul.append(li); });
Deutsch
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Wir verwenden Cookies für den Betrieb der Website, Analyse und Personalisierung. Die Datenverarbeitung erfolgt gemäß der Datenschutzerklärung.
alle akzeptieren anpassen ablehnen