使用事件侦听器记录表数组中的哪个单元格已被单击

时间:2016-05-22 19:26:25

标签: javascript

也许是一个愚蠢的问题,但我刚刚开始学习JS。

如何使用以下代码(例如)记录单击了哪个表格单元格。



// 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);
  });
}
&#13;
<!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>
&#13;
&#13;
&#13;

登录董事会[i]或[i]不工作;我总是出现9,而且[i]未定义。

编辑:做一些挖掘,我设法偶然发现了一些东西并把它们放在一起使它们起作用。

但是,我仍然没有真正理解它是如何运作的。

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

5 个答案:

答案 0 :(得分:1)

您误解的是语句变量i是块作用域的。但是在JavaScript中用var初始化的变量是函数作用域。因此,在事件被触发时,变量i9,因为循环已完成。

使用ES2015,您可以将var替换为let并完成,因为let使用块范围初始化变量:

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

但这仅适用于新浏览器,或者当您使用babel将代码转换为ES5时。

您必须为i引入新的范围,以便为每次迭代保留i的值,以使其在没有let

的情况下正常工作
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));
}

答案 1 :(得分:0)

只是不要在点击内使用i变量并将其替换为此。正如你在这里看到的那样 -

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

答案 2 :(得分:0)

您可以将事件注入函数以获取对事件的目标(在本例中为td元素)的引用,然后获取innerText或innerHtml,如下所示:

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

答案 3 :(得分:0)

首先,将您的函数移出循环以保存多次重新创建相同的函数。然后,在函数内部,只需使用this关键字来访问被点击的元素:

&#13;
&#13;
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);
}
&#13;
<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>
&#13;
&#13;
&#13;

或者,您可以将事件处理委托给祖先<table>元素:

&#13;
&#13;
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);
&#13;
<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>
&#13;
&#13;
&#13;

答案 4 :(得分:0)

这是众所周知的错误。

  

在循环中创建闭包:一个常见的错误   见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

这可以解决您的问题

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