Refactoring des Standards onClick
innerhalb des HTML-Tags für Listener, bei denen ein Problem mit meinem Code aufgetreten ist:
var td;
for (var t=1;t<8;t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(td);
})}
}
Wenn das td
-Element angeklickt wird, wird davon ausgegangen, dass auf td
mit dem letzten Index aus der Schleife geklickt wurde, z. 7
Sieht aus, als wäre eventListeners
nur für das letzte Element in dieser Schleife aufgefüllt worden.
Die Loop-Initialisierung sieht korrekt aus.
.__ Warum ist das passiert?
Hier ist Live-Code
Sie müssen die Zuweisung des Ereignis-Listeners wie folgt abschließen:
var td;
for (var t = 1; t < 8; t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener === 'function'){
(function (_td) {
td.addEventListener('click', function(){
console.log(_td);
});
})(td);
}
}
Die Variable td
wird außerhalb Ihrer Event-Handler definiert. Wenn Sie auf eine Zelle klicken, protokollieren Sie den letzten Wert, auf den sie festgelegt wurde.
Technisch gesehen: Jede Event-Handler-Funktion ist eine Schließung - eine Funktion, die auf Variablen aus einem äußeren Bereich verweist.
Die allgemeine Lösung für diese Art von Problem besteht darin, den Ereignishandler von einer Wrapper-Funktion zurückzugeben, wobei die zu überwachenden Variablen als Argumente übergeben werden:
td.addEventListener('click', function(wrapTD) {
return function() { console.log(wrapTD); }
}(td));
Die Argumente sind jetzt an den Bereich der aufgerufenen Wrapper-Funktion gebunden.
this
Es gibt jedoch eine noch einfachere Option. In einem Event-Handler wirdthis
auf das Element gesetzt, für das der Handler definiert ist , sodass Sie statt this
einfach td
verwenden können:
td.addEventListener('click', function() {
console.log(this);
});
Schließlich können Sie Sie können die for
-Schleife vollständig loswerden und einen einzelnen Event-Handler für die gesamte Tabelle festlegen:
var table = document.getElementById('my-table');
table.addEventListener('click', function(e) {
if (e.target.nodeName.toUpperCase() !== "TD") return;
var td = e.target;
console.log(td);
});
Dies ist eine viel bessere Lösung für größere Tabellen, da Sie mehrere Ereignishandler durch nur einen ersetzen. Wenn Sie Ihren Text in ein anderes Element einschließen, müssen Sie dies anpassen, um zu prüfen, ob das Zielelement ein Nachkomme einer td
ist.
Was hier passiert, ist, dass Sie die Variable 'td' im Gültigkeitsbereich der Ereignis-Listener-Funktion behalten. Es gibt nur eine Instanz von 'td', die jedes Mal aktualisiert wird, wenn die for-Schleife wiederholt wird. Wenn die for-Schleife beendet ist, wird der Wert von td nun auf das Element '# td7' gesetzt, und Ihr Event-Handler protokolliert einfach den aktuellen Wert von td.
In dem obigen Beispiel können Sie einfach "das Folgende" protokollieren:
var td;
for (var t=1;t<8;t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(this);
});
}
}
da 'this' auf das Element gesetzt ist, an das ein Ereignis für die Ausführung eines Ereignishandlers gebunden war.
Ich schätze, Sie suchen nach einer Antwort darauf, wie Sie den Iterator festhalten, wenn Sie Closures innerhalb einer for-Schleife erstellen. Dazu möchten Sie eine Funktion außerhalb der for-Schleife definieren.
for (var t=1;t<8;t++){
bind_event(t);
}
function bind_event(t) {
var td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(td);
});
}
}
Auf diese Weise wird bei jeder Ausführung von bind_event eine Instanz einer Variablen mit dem Namen 'td' erstellt, und diese Instanz wird für die Ereignislistenerfunktion geschlossen. Es ist erwähnenswert, dass 't' in bind_event auch eine neue Variable ist.
Wie ich es verstehe, geschieht dies aufgrund der Schließung ... Sie weisen Event Handler im Rahmen der FOR-Anweisung zu. Wenn ein Klick erfolgt, wird die letzte Version von TD im Geltungsbereich von FOR benötigt und in das Protokoll geschrieben.
folgendes sollte wie erwartet funktionieren:
for (var t=1;t<8;t++){
var td;
td = document.getElementById('td'+t);
if (typeof window.addEventListener==='function'){
td.addEventListener('click',function(){
console.log(this);
})}
}