复选框 $.change 被自身触发并循环,因为它正在 $.change 内部被修改

Posted

技术标签:

【中文标题】复选框 $.change 被自身触发并循环,因为它正在 $.change 内部被修改【英文标题】:checkbox $.change is being triggered by itself and looping because it is being modified inside $.change 【发布时间】:2017-08-24 20:49:43 【问题描述】:

我有一组复选框,当您单击一个时,它们都应该被选中。

当用户单击一个复选框时,它会检查以该类名称开头的所有其他复选框。我想要的是用户点击一个复选框,$(".atpSelections").change 每次点击只触发一次

代码如下:

        $(".atpSelections").change(function() 
            console.log("CHANGED");

            //Check ALL other checkboxes starting with that class name:
            var className = $(this).attr("class");
            className=className.replace("atpSelections ", "");
            className=className.trim();
            className=className.split("-");

            //Get current checkbox state
            var currentState = $(this).attr("checked");

            //Now loop through all other checkboxes starting 
            //with the same class name and check them:
            $("input[class*='"+className[0]+"-']").each(function(i)
                    //THIS IS TRIGGERING "$(".atpSelections").change"!!
                    if(currentState && currentState=="checked")
                    
                        $(this).prop('checked', true);
                    else
                    
                        $(this).prop('checked', false);
                    
                );
        );

问题

问题是,当用户单击一个复选框时,$(".atpSelections").change 方法会被反复触发,因为$(this).prop('checked', true); 会再次触发$(".atpSelections").change,而且它只是循环往复。

所以 1 单击复选框会触发 100 次“更改”事件,而我只希望它触发 一次。

如何在不再次触发$(".atpSelections").change 的情况下更改$(".atpSelections").change 内的复选框状态?

尝试

我尝试将$(".atpSelections").change 更改为$(".atpSelections").click,但遇到了同样的问题。我认为$(this).prop('checked', true); 触发了click 事件。

解决方案

我使用了@James 的答案并改变了

var currentState = $(this).attr("checked");

var currentState = $(this).prop("checked") ? "checked" : "";

而且效果很好!谢谢。

这是 JSFiddle: https://jsfiddle.net/zL7amo0y/

【问题讨论】:

以编程方式更改选中的属性不会触发更改事件。你能分享html吗?到目前为止,您的代码很混乱 能否在 Question 中包含 html,创建 stacksn-ps 来演示问题? currentState 不包含您期望的内容,请使用var currentState = $(this).prop("checked") ? "checked" : ""; 【参考方案1】:

问题在于您的 currentState 变量。请在上面做一个console.log。我猜它是未定义的?

以下是您在 jQuery 和 Vanialla JS 中修复的代码。

JQuery:

       $(".atpSelections").change(function() 

            var currentState = $(this).prop("checked");
            console.log(currentState);

            $("input[name='checkboxToCheck']").each(function(i)
                    if(currentState)
                    
                        $(this).prop('checked', true);
                    else
                    
                        $(this).prop('checked', false);
                    
                );
        );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="myForm">
			<label for="checkbox1">Main Checkbox:</label>
			<input class="atpSelections" value="checkbox1" type="checkbox" id="checkbox1" />

			<label for="checkbox2">Checkbox2:</label>
			<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />

			<label for="checkbox3">Checkbox3:</label>
			<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
		</form>

原版JS:

			var checkbox = document.getElementById("checkbox1")
			var checkboxToCheck = document.getElementsByName("checkboxToCheck");
			checkboxToCheck = [].slice.call(checkboxToCheck);

			function checkAllBoxes() 

				checkboxToCheck.forEach((element) => 
					if (checkbox.checked) 
						element.checked = true;
					 else 
						element.checked = false;
					
				);

			

			checkbox.addEventListener("change", checkAllBoxes);
		<form name="myForm">
			<label for="checkbox1">Main Checkbox:</label>
			<input value="checkbox1" type="checkbox" id="checkbox1" />

			<label for="checkbox2">Checkbox2:</label>
			<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />

			<label for="checkbox3">Checkbox3:</label>
			<input name="checkboxToCheck" value="checkbox1" type="checkbox" id="checkbox1" />
		</form>

【讨论】:

【参考方案2】:

我在想知道你的问题是什么,我也用复选框插件解决了这个问题。

试试这个

$(".atpSelections").on('change.custom', function(e) 
   console.log("CHANGED CUSTOM");

   //Check ALL other checkboxes starting with that class name:
   var className = $(this).attr("class");
   className=className.replace("atpSelections ", "");
   className=className.trim();
   className=className.split("-");

   //Get current checkbox state
   var currentState = $(this).attr("checked");

   //Now loop through all other checkboxes starting 
   //with the same class name and check them:
   $("input[class*='"+className[0]+"-']")
     .off('change.custom')
     .each(function(i)
       //THIS IS TRIGGERING "$(".atpSelections").change"!!
       if(currentState && currentState=="checked")
         $(this).prop('checked', true);
       else
         $(this).prop('checked', false);
       
   );
 );

通常没关系:)

【讨论】:

以上是关于复选框 $.change 被自身触发并循环,因为它正在 $.change 内部被修改的主要内容,如果未能解决你的问题,请参考以下文章

事件处理

python中select点击option触发

更改复选框未触发

easyui combobox 用代码赋值不触发change事件,选择值会触发

Dynamics CRM Form表单中通过javascript抓取触发change事件字段的属性名

循环检查复选框并计算每个选中或未选中的复选框