2016-05-22 3 views
0

Vielleicht eine dumme Frage, aber ich fange gerade an, JS zu lernen.Protokollierung, welche Zelle im Tabellenarray mit Ereignis-Listener angeklickt wurde

Wie würde ich protokollieren, welche Tabelle Zelle mit dem folgenden Code angeklickt wurde (als Beispiel).

// Get array of td elements; 9 cells for game board 
 
var board = document.getElementsByTagName("td"); 
 
for (var i = 0; i < board.length; i++) { 
 
    console.log(board[i]); 
 
    board[i].addEventListener("click", function() { 
 
    console.log(board[i]); 
 
    console.log(i); 
 
    }); 
 
}
<!DOCTYPE html> 
 
<html> 
 

 
<body> 
 

 

 

 
    <table border="1"> 
 
    <tr> 
 
     <td>1</td> 
 
     <td>2</td> 
 
     <td>3</td> 
 
    </tr> 
 
    <tr> 
 
     <td>4</td> 
 
     <td>5</td> 
 
     <td>6</td> 
 
    </tr> 
 
    <tr> 
 
     <td>7</td> 
 
     <td>8</td> 
 
     <td>9</td> 
 
    </tr> 
 
    </table> 
 

 
</body> 
 

 
</html>

Loggin entweder board [i] oder [i] nicht funktionieren; Ich komme immer als 9, und Board [i] kommt undefined.

EDIT: Beim Graben habe ich es geschafft, über einige Dinge zu stolpern und sie zusammen zu werfen, damit sie funktionieren.

Ich verstehe immer noch nicht ehrlich, wie es funktioniert, obwohl.

function testf(i) { 
    return (function(){ 
      console.log("you clicked region number " + i); 
     }); 
} 
// Trigger function cellClicked() when any table cell is clicekd 
for (var i = 0; i < board.length; i++) { 
    board[i].addEventListener("click", testf(i)); 
} 

Antwort

1

Was Sie fehlinterpretieren ist, dass die Anweisungsvariable i Blockbereich ist. Aber Variablen, die mit var in JavaScript initialisiert wurden, sind Funktionsbereiche. Zum Zeitpunkt des Ereignisses ist die Variable i also 9, weil die Schleife beendet ist.

Mit ES2015 können Sie var mit let ersetzen und Sie sind fertig, weil let eine Variable mit Block Umfang initialisiert:

for (let i = 0; i < board.length; i++) { 
    console.log(board[i]); 
    board[i].addEventListener("click", function() { 
    console.log(board[i]); 
    console.log(i); 
    }); 
} 

Das funktioniert aber nur in neuen Browser oder wenn Sie transpiling Ihren Code mit bis zu ES5 babel zum Beispiel.

Sie haben einen neuen Rahmen für die i einzuführen für jede Iteration den Wert von i zu halten, um es ohne let funktioniert

function handleClick(i) { 
    // function sets new scope for i 
    return function() { 
    console.log(board[i]); 
    console.log(i); 
    } 
} 

for (let i = 0; i < board.length; i++) { 
    console.log(board[i]); 
    board[i].addEventListener("click", handleClick(i)); 
} 
0

Verwenden Sie einfach nicht die Variable i innerhalb des Klicks und ersetzen Sie sie mit diesem. Wie Sie hier-

board[i].addEventListener("click", function() { 
    console.log(this); 
    console.log(this.innerHTML); 
    }); 
0

sehen können Sie das Ereignis an die Funktion injizieren einen Verweis auf die Veranstaltungs-Ziel (das td-Element in diesem Fall) zu bekommen, dann bekommen die Innertext oder innerhtml, wie folgt aus:

board[i].addEventListener("click", function(event) { 
    console.log(event.target.innerText); 
}); 
0

Zuerst bewegen Sie die Funktion außerhalb der Schleife, das gleiche zu speichern Neuer Funktion mehrmals. Und dann, in der Funktion, verwenden Sie einfach die this Schlüsselwort das geklickt Element zuzugreifen:

function log(){ 
 
    // this is passed from the EventTarget.addEventListener() 
 
    // method: 
 
    console.log(this, this.textContent); 
 
} 
 

 
// Get array of td elements; 9 cells for game board 
 
var board = document.getElementsByTagName("td"); 
 
for (var i = 0; i < board.length; i++) { 
 
    board[i].addEventListener("click", log); 
 
}
<table border="1"> 
 
    <tr> 
 
    <td>1</td> 
 
    <td>2</td> 
 
    <td>3</td> 
 
    </tr> 
 
    <tr> 
 
    <td>4</td> 
 
    <td>5</td> 
 
    <td>6</td> 
 
    </tr> 
 
    <tr> 
 
    <td>7</td> 
 
    <td>8</td> 
 
    <td>9</td> 
 
    </tr> 
 
</table>

Alternativ könnten Sie die Ereignisbehandlung an den Vorfahren <table> Element delegieren:

function log(e){ 
 
    // this is passed from the EventTarget.addEventListener() 
 
    // method, but here refers to the <table> element, to find 
 
    // the clicked <td> element we need to look at the 
 
    // target property of the 'event' (here 'e') also passed 
 
    // from the addEventListener() method: 
 
    console.log(this, e.target, e.target.textContent); 
 
} 
 

 
// retrieving the first/only <table> element on the page, 
 
// adding the event-listener for the click-event and 
 
// binding the log() function as the event-handler: 
 
var board = document.querySelector('table').addEventListener('click', log);
<table border="1"> 
 
    <tr> 
 
    <td>1</td> 
 
    <td>2</td> 
 
    <td>3</td> 
 
    </tr> 
 
    <tr> 
 
    <td>4</td> 
 
    <td>5</td> 
 
    <td>6</td> 
 
    </tr> 
 
    <tr> 
 
    <td>7</td> 
 
    <td>8</td> 
 
    <td>9</td> 
 
    </tr> 
 
</table>

0

Dies ist ein bekannter Fehler.

Erstellen von Schließungen in Schleifen: Ein häufiger Fehler
Siehe https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

und dies ist für Ihr Problem beheben

window.onload = function() { 
    function logEvent(a, b) {//closure function 
     return function() { 
      console.log(a);//values from outer function 
      console.log(b); 
     } 
    } 
    var board = document.getElementsByTagName("td"); 
    for (var i = 0; i < board.length; i++) { 
     console.log(board[i]); 
     var log = logEvent(board[i].innerHTML, i);//take values when they exist 
     board[i].addEventListener("click", log); 
     //board[i].addEventListener("click", logEvent(board[i].innerHTML, i));//this way is also possible 
    } 
} 
Verwandte Themen