我可以将 EventListener 放在 <option> 元素上吗?

Can I put an EventListener on an <option> element?

我正在尝试将 EventListener 添加到 <option> 元素。

我尝试了各种方法,但没有结果。 我正在使用 VueJS,所以我尝试使用他们的事件绑定机制。

VueJS - 事件绑定 - 仅适用于 <select>

<select @mouseover="testValue = true" @mouseleave="testValue = false" ref="select">
  <option v-for="(option, index) in selectionSet" :key="index"
          :value="option.id" :disabled="option.disabled" @mouseover="testValue = true" @mouseleave="testValue = false">
    {{option.name}}
  </option>
</select>

所以接下来我自然而然地采用了 RAW plainJS 方式。

PlainJS - AddEventListener() - 元素有效,但 eventListener 不会被注册

this.$refs.select.options.forEach((el) => {
  el.addEventListener('pointerover', () => { window.console.log('AAAAH'); });
  if (!el.disabled) window.console.log(el.value);
});

是的,我使用了多个事件名称。


那怎么办? -> 阅读文档

调查<option> documentation on MDN, I can see, that the <option> has the HTMLOptionElement DOM Interface. This interface is supposed to have all Properties and Methods inherited from HTMLElement

The HTMLOptionElement interface represents elements and inherits all properties and methods of the HTMLElement interface. - MDN

所以我想知道,我能否以某种方式将 eventListeners 注册到 <option> 元素?

问题不在于在元素上注册事件处理程序,而是浏览器不会在下拉列表中的 option 元素(或者至少,不能可靠地跨浏览器)触发事件select 个元素。

例如,

Chrome 和 Firefox 不会在下拉 select 元素中的 option 元素上触发任何事件,即使你可以在它们上注册事件处理程序,甚至在它们上触发您自己的事件。例如,在下面,Chrome 或 Firefox 不会在 option 元素上自动触发任何事件,但是如果您单击按钮明确地触发一个,它会起作用:

const option = document.querySelectorAll("option")[1];

function optionEventHandler(event) {
    console.log(event.type, this.textContent);
}

// None of these fire on Chrome except when code explicitly
// does it with `dispatchEvent`, as far as I can tell:
for (const eventName of ["click", "mouseover", "pointerover", "mouseenter"]) {
    option.addEventListener(eventName, optionEventHandler);
}

document.querySelector("select").addEventListener("click", function() {
    console.log("click on select", this.value);
});

// Explicitly firing an event at the element:
document.querySelector("input[type=button]").addEventListener("click", function() {
    option.dispatchEvent(new Event("click"));
});
<select>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
<option>E</option>
</select>
<div>
    <input type="button" value="Send 'click' to B">
</div>

很遗憾,如果您想在指针位于选项上方时执行某些操作,则必须使用 selectoption 以外的其他选项。当指针从列表中的一个 option 移动到下一个

时,Chrome 和 Firefox 甚至都不会在 document 触发 pointerover

为了完整起见,请注意某些事件(包括 pointerover)在非下拉 select 元素中起作用,至少在 Chrome 和 Firefox 上是这样:

const option = document.querySelectorAll("option")[1];

function optionEventHandler(event) {
    console.log(event.type, this.textContent);
}

// None of these fire on Chrome except when code explicitly
// does it with `dispatchEvent`, as far as I can tell:
for (const eventName of ["click", "mouseover", "pointerover", "mouseenter"]) {
    option.addEventListener(eventName, optionEventHandler);
}

document.querySelector("select").addEventListener("click", function() {
    console.log("click on select", this.value);
});

// Explicitly firing an event at the element:
document.querySelector("input[type=button]").addEventListener("click", function() {
    option.dispatchEvent(new Event("click"));
});
<select size="5">
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
<option>E</option>
</select>
<div>
    <input type="button" value="Send 'click' to B">
</div>