jQuery .更改 DRY 代码

jQuery .change DRY code

我使用“bootstraptoggle”插件将复选框放在一起。我正在根据选中的框构建 mongoDB 查询。

代码完美无缺,但我讨厌重复 .change,有什么办法让它变干吗?

我有以下代码

HTML

<div id="checkBoxContainer" class="container">
     <label class="checkbox-inline">
          <input type="checkbox" id="optionOne" data-onstyle="success" data- offstyle="danger" data-toggle="toggle">
     </label>
     <label class="checkbox-inline">
          <input type="checkbox" id="optionTwo" data-onstyle="success" data- offstyle="danger" data-toggle="toggle">
     </label>
</div>

JS

$('#optionOne').change(function() {
    if ($(this).prop('checked') == true) {
        queryBuilder.push($(this).attr("id"));
    } else if ($(this).prop('checked') == false) {
        queryBuilder.splice($(this).attr("id"));
    }
    console.log(queryBuilder);
});


$('#optionTwo').change(function() {
    if ($(this).prop('checked') == true) {
        queryBuilder.push($(this).attr("id"));
    } else if ($(this).prop('checked') == false) {
        queryBuilder.splice($(this).attr("id"));
    }
    console.log(queryBuilder);
});

我已经搜索并尝试了以下但没有成功。

$('document').on('change','#checkBoxContainer', function() {    
      if ($(this).prop('checked') == true) {
        queryBuilder.push($(this).attr("id"));
    } else if ($(this).prop('checked') == false) {
        queryBuilder.splice($(this).attr("id"));
    }
    console.log(queryBuilder);

});

is there any way to make this DRY?

$('#optionOne, #optionTwo').change(...);

这叫做selector group。 None 更改处理程序中的代码特定于它挂钩的元素,因此纯粹是将它挂接到两个元素的问题。


无关,但是:这一行是可疑的:

queryBuilder.splice($(this).attr("id"));

splice 需要至少两个参数:开始执行操作的索引,以及要在该位置删除的元素数(可能为 0,如果您随后要有更多参数指定要插入的内容)。

如果您的目标是从数组中删除 $(this).attr("id") 的值,那是行不通的。相反:

var index = queryBuilder.indexOf($(this).attr("id"));
if (index != -1) {
    queryBuilder.splice(index, 1);
}

如果它存在,它会找到它,然后将其删除。


旁注:

正如斜眼所说,$(this).attr("id")只是写了this.id,而$(this).prop("checked")只是写了this.checked。 :-)

也从来没有任何理由在进行比较时写 == true很少,有理由写 === true)。

最后,由于 checked 只能是真或假,所以不需要第二个 if

所以:

$('#optionOne, #optionTwo').change(function() {
    var index;
    if (this.checked) {
        queryBuilder.push(this.id);
    } else {
        index = queryBuilder.indexOf(this.id);
        if (index != -1) {
            queryBuilder.splice(index, 1);
        }
    }
    console.log(queryBuilder);
});

或稍短:

$('#optionOne, #optionTwo').change(function() {
    var index;
    if (this.checked) {
        queryBuilder.push(this.id);
    } else if ((index = queryBuilder.indexOf(this.id)) != -1) {
        queryBuilder.splice(index, 1);
    }
    console.log(queryBuilder);
});

明显过度分析,我会注意到,如果我们认为在未选中复选框时它有可能出现在数组中,我们应该是更具防御性以避免将其放入两次:

$('#optionOne, #optionTwo').change(function() {
    var index = queryBuilder.indexOf(this.id);
    if (this.checked && index == -1) {
        queryBuilder.push(this.id);
    } else if (!this.checked && index != -1) {
        queryBuilder.splice(index, 1);
    }
    console.log(queryBuilder);
});

好的,我现在停下来。 :-)


啊,还有一件事:一些 非常旧的 浏览器没有 Array#indexOf,所以如果你需要支持它们,你需要添加一个垫片或使用 jQuery 的严重错误命名 $.inArray 代替。要使用 inArray,请将 queryBuilder.indexOf(this.id) 更改为 $.inArray(queryBuilder, this.id)(无需更改其他内容)。

对常用项目使用常用 class 是最简单的方法:

<input class="option-class" type="checkbox" id="optionTwo">

.

$('.option-class').change(/* your handler code */);

虽然 ID 是最容易定位的选择器,但人们会坚持使用它们,并且在使用 classes 重复组件时,通过定位一组元素而不是一次一个元素,可以更轻松地干燥代码