简体   繁体   English

javascript onclick 事件未正确触发

[英]javascript onclick event not firing correctly

I have this click event attached to each button and when I click on each of them, it is printing the output meant for the third button.我将这个点击事件附加到每个按钮,当我点击每个按钮时,它正在打印第三个按钮的输出。 I'm not sure what is going on.我不确定发生了什么。

<!DOCTYPE html>
<html>
<head>
  <title>JS Bin</title>
</head>
<body>
  <button>test1</button>
  <button>test2</button>
  <button>test3</button>
</body>
<script>
   var nodes = document.getElementsByTagName('button');
   for (var i = 0; i < nodes.length; i++) {
       nodes[i].addEventListener('click', function() {
       console.log('You clicked element #' + i);
   });
   }
</script>
</html>

when I click on any of the buttons, it is printing当我点击任何按钮时,它正在打印

"You clicked element #3"

Simple solution to this:对此的简单解决方案:

<!DOCTYPE html>
<html>

<head>
    <title>JS Bin</title>
</head>

<body>
    <button>test1</button>
    <button>test2</button>
    <button>test3</button>
</body>
<script>
    var nodes = document.getElementsByTagName('button');
    console.log(nodes);
    for (var i = 0; i < nodes.length; i++) {
        //converted click function into an IIFE so it executes then and there only
        nodes[i].addEventListener('click', (function (j) {
            return function () {
                console.log('You clicked element #' + j);
            }

        })(i));
    }
</script>

</html>

You should go through two concepts to understand this thing你应该通过两个概念来理解这个东西

1) Closures 1) 关闭

2) Javascript is single-threaded and synchronous. 2) Javascript 是单线程和同步的。 So how does it handle events?那么它是如何处理事件的呢?

Here is what it is happening in your code:这是您的代码中发生的事情:

==> for loop gets executed synchronously as it is part of javascript engine post which javascript handles event queue which is a FIFO (first in first out) ==> for 循环同步执行,因为它是 javascript 引擎 post 的一部分,javascript 处理事件队列,这是一个 FIFO(先进先出)

==> When for loop finished value of i is three which remains in memory until the function inside it executes ==> 当 for 循环结束时 i 的值为 3,它会保留在内存中,直到它内部的函数执行

==> Each time it takes a value 3 and prints it. ==> 每次取值 3 并打印它。

This is the closure with function inside a loop issue.这是循环问题中的函数闭包。

JavaScript closure inside loops – simple practical example 循环内的 JavaScript 闭包——简单实用的例子

Watch out for this!小心这个!

Side note: questions around this issue are frequently asked in interviews to demonstrate proficiency with JS.旁注:围绕这个问题的问题在面试中经常被问到,以证明对 JS 的熟练程度。

When this button is listening to event, at that time the value of i is nodes.length -1 that is 2 .当这个button正在监听事件时,此时i的值是nodes.length -1 即2 Because loop has already finished it's execution and have set value of i to 2.因为循环已经完成它的执行并将i值设置为 2。

So it is consoling You clicked element #3 .所以它是安慰You clicked element #3

Such issues arise because of scope & closure由于scopeclosure出现此类问题

Create an IIFE and pass the value of i .创建一个IIFE并传递i的值。

Hope this snippet will be useful希望这个片段会有用

  var nodes = document.getElementsByTagName('button');
   for (var i = 0; i < nodes.length; i++) {
   (function(i){
   nodes[i].addEventListener('click', function() {
       console.log('You clicked element #' + i);
   });
}(i))

   }

Check this jsfiddle检查这个jsfiddle

This is other way using jQuery.这是使用 jQuery 的另一种方式。

$("button").each(function(e) {
    $(this).data("number", e);
}).bind("click", function(e) {
    console.log("You clicked element #" + $(this).data("number"));
});

https://jsfiddle.net/ChaHyukIm/uxsqu70t/3/ https://jsfiddle.net/ChaHyukIm/uxsqu70t/3/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM