首页 > 解决方案 > 为什么 .on('click', function(){}) 在附加处理程序后似乎执行该函数而没有发生任何实际点击?

问题描述

我正在尝试制作一个选择框,如果您单击活动选择,它将取消选择所有内容。但似乎选择框的更改事件在选项的单击事件之前触发。这会导致在更改事件触发期间添加的事件处理程序附件被触发,而在附加事件处理程序后实际上没有发生任何点击。解决这个问题的最佳方法是什么?

复选框单击事件在 Firefox 中的更改事件之前触发,这与 chrome 不同, 这提供了 setTimeout 作为绕过它的一种方式。但是在这种情况下,我不能这样做,因为我根本不希望更改事件触发。或者,如果有一种方法可以使第一个更改事件中的点击事件静音,那也可以,但我认为没有办法做到这一点,或者有吗?

我一直在用小提琴尝试它。我创造了

  1. 一个复选框来说明我想要实现的概念。
  2. 只有一个选项的选择框使用相同的代码来说明问题
  3. 一个更详细的例子,我最终想要做的不止一个选项

我用来附加处理程序的事件处理程序如下所示。有关完整代码,请参阅小提琴。

$(jqID+" option:selected").on("click", function(){
         deSelect($(this).attr('id'));
});

// Checkbox test code that starts with change when first check was made, and subsequent showing click bloc code only on second click -> that is the expected behavior
$("#checkbox").on('change', function() {
  console.log("changed");

  $("#checkbox").on('click', function() {
    console.log("clicked");
    $("#checkbox").off('click');
    console.log("click evthandler off");
  });
  console.log("click evthandler on");
});

// Select code with exact same set up
$("#selectbox").on('change', function() {
  console.log("selbox changed");

  $("#SO1").on('click', function() {
    console.log("selopt clicked");
    $("#SO1").prop("selected", false); //Added this line to deselect option
    $("#SO1").off('click');
    console.log("selopt click evthandler off");
  });
  console.log("selopt click evthandler on");
});

// Select box code: ______________________________________
// Attach the original change event handler like the above
$("#S1").on("change", function() {
  toggleSelected("S1")
});

// toggleSelected baseically turns off all option level click event handlers, and then it adds it back on for only the actively selected option currently.
function toggleSelected(jsID) {
  var jqID = "#" + jsID;
  var selElements = $(jqID + " option:selected");
  var allTargets = $(jqID);

  console.log("toggleSelected Executed");

  // Cleans out all event handlers on the options
  allTargets.children("option").off("click");

  // Attaches event handler for active option
  if (typeof selElements !== "undefined" && selElements.length == 0) {
    console.log("no elements selected or error reading selection set");
  } else {
    console.log("before attaching event handler for clicks");
    $(jqID + " option:selected").on("click", function() {
      console.log("within click function before deSelect");
      deSelect($(this).attr('id'));
      console.log("within click function after deSelect");
    });
    console.log("after attaching event handler for clicks");
  }
}

// deSelect is deselects the option. Test functions have been removed for ease of reading
function deSelect(jsID) {
  console.log("deSelect Executed");

  $("#" + jsID).prop("selected", false); //This deselects the option

  console.log("deSelect refresh calling of toggleSelected");
  toggleSelected("S1"); //I just did S1 for the sake of simplicity here.
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="checkbox" type="checkbox">

<select id="selectbox" class="catSelect" title="Taa" size="4">
  <option id="SO1" value="1" class="catOptions">Laa</option>
</select>

<select id="S1" class="catSelect" title="Taa" size="4">
  <option id="SO1" value="1" class="catOptions">Laa</option>
  <option id="SO2" value="2" class="catOptions">Paa</option>
  <option id="SO3" value="3" class="catOptions">Waa</option>
  <option id="SO4" value="4" class="catOptions">Maa</option>
</select>

JS小提琴

如您所见,复选框按预期工作。在第一次点击时,它只显示:

并且不包括

当在选择框上进行选择时,控制台日志显示如下:

这清楚地表明单击确实触发了,但实际上是在更改处理程序完成其工作之后。

我怎样才能使选择选项时的结果是:


第三个选择框基本相同,但有更多的测试选项。这可能会有所帮助,但如果您只需要了解我遇到的问题,您可以跳过它。但是第三个盒子的期望行为是:

其余部分仅在随后单击所选选项时才显示:

标签: jqueryevent-handling

解决方案


推荐阅读