带有动态jQuery选择器的循环事件处理程序

时间:2016-12-23 13:08:39

标签: javascript jquery for-loop click

我想要的是点击#bt-1并更改#target-1的颜色,点击#bt-2并更改#target-2的颜色... 我开始为每个#bt-n / #target-n编写一个特定的点击事件处理程序,但随着网站变大,我想到了使用循环。我的方法是在jQuery选择器中使用带有变量的for循环。这是我的代码:



$(document).ready(function() {
  
  var total = $('.target').length;
  for(n=1; n<=total; n++) {
    var num = String(n);
    $('#bt-'+num).on('click', function() {
      $('#target-'+num).toggleClass('yellow');
    });
  }
  
});
&#13;
.wrapper {
  display: flex;
  text-align: center;
}
.button, .target {
  padding: 20px;
  margin: 10px;
}
.button {
  background: gray;
}
#target-1 {
  background: red;
}
#target-2 {
  background: green;
}
#target-3 {
  background: blue;
}
.yellow {
  background: yellow !important;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div id="bt-1" class="button">
    <h1>Button 1</h1>
  </div>
  <div id="target-1" class="target">
    <h1>Target 1</h1>
  </div>
</div>
<div class="wrapper">
  <div id="bt-2" class="button">
    <h1>Button 2</h1>
  </div>
  <div id="target-2" class="target">
    <h1>Target 2</h1>
  </div>
</div>
<div class="wrapper">
  <div id="bt-3" class="button">
    <h1>Button 3</h1>
  </div>
  <div id="target-3" class="target">
    <h1>Target 3</h1>
  </div>
</div>
&#13;
&#13;
&#13;

我不明白为什么它只针对最后一个#target-n,因为循环似乎正在#bt-n上运行。我还想过使用数组,但无法弄清楚如何实现它。

我设法使用$(this).siblings('.target')...使其不需要for循环和ID,但每个.button / .target都有父元素,在这种情况下.wrapper Code Here。虽然这是一个很好的解决方案,但我想了解我做错了什么以及如何在不使用父.wrapper的情况下正确实现循环来实现这一点。谢谢。

2 个答案:

答案 0 :(得分:2)

只有最后一项受到影响的原因是因为在任何事件触发之前循环已完成。因此n保存循环中的最后一个值。要解决此问题,您需要使用闭包:

for (n = 1; n <= total; n++) {
  (function(n) {
    $('#bt-' + n).on('click', function() {
      $('#target-' + n).toggleClass('yellow');
    });
  })(n);
}

也就是说,一个更好的方法是避免循环并使用DOM遍历来查找与点击的.target相关的.button,如下所示:

$('.button').click(function() {
  $(this).next('.target').toggleClass('yellow');
});
.wrapper {
  display: flex;
  text-align: center;
}
.button,
.target {
  padding: 20px;
  margin: 10px;
}
.button {
  background: gray;
}
#target-1 {
  background: red;
}
#target-2 {
  background: green;
}
#target-3 {
  background: blue;
}
.yellow {
  background: yellow !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div id="bt-1" class="button">
    <h1>Button 1</h1>
  </div>
  <div id="target-1" class="target">
    <h1>Target 1</h1>
  </div>
</div>
<div class="wrapper">
  <div id="bt-2" class="button">
    <h1>Button 2</h1>
  </div>
  <div id="target-2" class="target">
    <h1>Target 2</h1>
  </div>
</div>
<div class="wrapper">
  <div id="bt-3" class="button">
    <h1>Button 3</h1>
  </div>
  <div id="target-3" class="target">
    <h1>Target 3</h1>
  </div>
</div>

答案 1 :(得分:0)

注册很多事件处理程序是不明智的。您可以绑定一个事件处理程序并对从元素id读取的给定特定idx执行操作,例如:

$('body').on('click', function (event) {
    if (!event.target.id.match(/^bt-\d+/)) {
        return; //id of clicked element does not match bt-{number}
    }

    var idx = event.target.id.replace('bt-', ''); //remove prefix "bt-" and leave only numeric postfix

    $('#target-' + idx).toggleClass('yellow');
});

说明:

click元素上绑定body您可以从未取消传递该事件的子元素访问所有click个事件。已点击的元素已保存在event.target内,并且id中的属性为event.target.id

在这个id属性上,我用正则表达式调用match函数 - 它将匹配从^开始bt-的字符串,并且任意数字\d至少有一个+

if (!event.target.id.match(/^bt-\d+/)) {
    return; //id of clicked element does not match bt-{number}
}

此声明已被否定,因此,如果此id格式不是bt-someNumber,则不会更进一步。

var idx = event.target.id.replace('bt-', '');

id代替bt-并用空字符串''取代$('#target-' + idx).toggleClass('yellow');

target-

最后,您正在使用与按钮相同的数字切换元素,但使用不同的前缀bt-代替$(function() { ... });

快乐的黑客攻击!