单击 vs 输入 vs 更改复选框?

Click vs Input vs Change for checkboxes?

我有一个表格。我只想在用户精确选中 8 个可用复选框中的 4 个时才允许提交表单;一旦用户选中了 4 个复选框,我想禁用其余未选中的复选框。

我应该为 click 事件添加一个挂钩吗?或者 input 事件?或者 change 事件?

我对似乎相互重复功能的事件数量感到不知所措。

我也对文档感到困惑。

MDN docs about input:

For <input> elements with type=checkbox or type=radio, the input event should fire whenever a user toggles the control, per the HTML5 specification. However, historically this has not always been the case. Check compatibility, or use the change event instead for elements of these types.

MDN docs about change:

Unlike the input event, the change event is not necessarily fired for each alteration to an element's value.

及以下:

Depending on the kind of element being changed and the way the user interacts with the element, the change event fires at a different moment:

MDN docs about click:

An element receives a click event when a pointing device button (such as a mouse's primary mouse button) is both pressed and released while the pointer is located inside the element.

练习:

下面的 JS fiddle 似乎暗示所有 3 个事件都是等价的。单击复选框、单击标签、聚焦复选框并按键盘上的 space 似乎都会触发所有三个事件。

const checkbox = document.querySelector('input[type=checkbox]');
for (const event of ['input', 'click', 'change']) {
  checkbox.addEventListener(event, () => {
    log.textContent = `${event}\n${log.textContent}`
  })
}
<label>Toggle <input type="checkbox" name="" id="">
</label>
<pre id="log"></pre>

根据文档,changeinput 似乎是等价的;根据文档,click 似乎不等同于其他 3 个,但实际上它似乎等同。

我们真的有 3 个事件相互重复功能吗?我使用哪个事件有什么关系吗?

还是我遗漏了什么?

它们没有重复。有细微差别。

change 一旦值或状态改变,元素失去焦点。

$('input').on('change', function(){
  console.log('changed');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" value="1">
<input type="text">

click 单击元素后发生。

input 一旦值或状态发生变化,就会在失去焦点之前立即发生。无论状态是否根据鼠标或键盘事件发生变化,都会发生这种情况。复选框可以通过单击它来改变状态,或者聚焦它并按下空格键。 click 事件不会捕获空格键状态更改。

$('input').on('change', function(){
  console.log('changed');
});

$('input').on('input', function(){
  console.log('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" value="1">
<input type="text">

要测试checkbox上没有焦点变化和空格键变化,可以点击输入框然后shift+tab让checkbox聚焦到空格键。从 fiddle 看来,对于复选框,更改和输入事件都会在它更改时发生,即使焦点没有丢失。

这与文本字段的行为方式不同。因此,在生成事件时,这两个元素之间似乎存在一些行为差异。与输入框相反,复选框似乎遵循不太严格的模式实现。

这 3 个事件相互重复了彼此的功能,因为您正在查看的复选框恰好是一种特殊情况。

例如,如果您要使用一个文本字段

  • 只要使用用户界面更改元素中的文本,就会触发事件 input
  • 只要文本元素失去焦点,事件 change 就会触发(在大多数浏览器上)。它只会触发一次,而不是在每次击键后触发。
  • 只要用户单击文本字段,事件 click 就会触发。

如果我们将此应用到复选框(请记住,复选框只能更改为一件事:checked => uncheckedunchecked => checked

  • 只要使用用户界面更改选中状态,事件 input 就会触发。
  • 事件 change 将在检查状态发生变化时触发 在元素 (or when the checkbox loses focus in IE) 中。
  • 事件 click 将在检查状态完成更改后触发。

这 3 个事件具有非常相似的功能(几乎重复),因为它们都试图做一些不同的事情,但在功能上对复选框做同样的事情。唯一的区别是细微的实现细节。

我会使用 click 来避免不同浏览器的用户出现问题。