HTML <select> 元素是否应该调度 `beforeinput` 事件?

yos*_*ahn 15 html javascript dom-events

MDN页面指出beforeinput

<input>当, <select>, 或<textarea>元素的值即将被修改时,DOM beforeinput 事件会触发

<select>明确提到支持该beforeinput活动。

根据我对规范的简单阅读,这似乎也是正确的:

可信目标:元素(具体来说:HTMLInputElement 等控件类型)或启用了 contenteditable 属性的任何元素

(强调我的)

然而,似乎没有浏览器实现它。我检查过 Chrome、Safari 和 Firefox。

我是否理解错误?

const sel = document.getElementById('pet-select')
sel.addEventListener('beforeinput', () => console.log('beforeinput!'))
sel.addEventListener('input', () => console.log('input!'))
Run Code Online (Sandbox Code Playgroud)
<label for="pet-select">Choose a pet:</label>

<select name="pets" id="pet-select">
    <option value="">--Please choose an option--</option>
    <option value="dog">Dog</option>
    <option value="cat">Cat</option>
    <option value="hamster">Hamster</option>
    <option value="parrot">Parrot</option>
    <option value="spider">Spider</option>
    <option value="goldfish">Goldfish</option>
</select>
Run Code Online (Sandbox Code Playgroud)

Kai*_*ido 4

MDN 页面从输入事件页面复制了其摘要,该页面确实在此元素上触发。我确实在那里开了一个 PR 来纠正这个问题。

beforeinput事件不应在 上触发<select>,就像它不会在非文本输入上触发一样:

addEventListener('input', () => console.log('input!'))
addEventListener('beforeinput', () => console.log('beforeinput!'))
Run Code Online (Sandbox Code Playgroud)
<input type=text placeholder="here it fires"><br>
<input type=checkbox><br>
<input type=radio><br>
<input type=file><br>
<input type=color>
Run Code Online (Sandbox Code Playgroud)

为了理解这一点,我们需要回顾历史,看看inputHTML 规范最初是如何设计该事件的。
经过一段时间后,它才被转移到 W3C/UI-Events 工作组。
另一方面,由 W3C/编辑小组起草beforeinput,然后转移到 W3C/UI-Events。

W3C/UI-Events 小组中的讨论清楚地表明,他们的意图是仅在来自用户键盘输入的更改时触发。他们甚至最初预计它不会因粘贴或剪切等操作而触发。


好的,但是为什么输入事件会在<select>其他非文本输入元素上触发?

这是因为 HTML 规范(现在由 WHATWG 处理)实际上仍然定义了输入事件并要求它发生:

对于他们所说的<select>元素:

当用户代理要发送选择更新通知时,在给定选择元素的用户交互任务源上对元素任务进行排队以运行以下步骤:

  1. 在 select 元素上触发名为 input 的事件,并将 bubbles 和 Composites 属性初始化为 true。

至于文字,<input> 他们说

当应用输入和更改事件时(除按钮和 type 属性处于隐藏状态之外的所有输入控件都是这种情况),将触发事件以指示用户已与控件进行交互。只要用户修改了控件的数据,就会触发输入事件。

对于复选框:radiofile输入,您会发现以下内容:

输入激活行为是运行以下步骤:

  1. 如果该元素未连接,则返回。

  2. 在气泡和组合属性初始化为 true 的元素上触发名为 input 的事件。

  3. 在 bubbles 属性初始化为 true 的元素上触发名为 Change 的事件。


beforeinputHTML 规范中唯一提及该事件的内容是在 11 天前添加的,但 PR 仅在全局范围内公开该事件,并没有更改其定义。