【问题标题】:Can I put an EventListener on an <option> element?我可以将 EventListener 放在 <option> 元素上吗?
【发布时间】:2021-11-10 10:34:15
【问题描述】:

我正在尝试将 EventListener 添加到 &lt;option&gt; 元素。

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

VueJS - 事件绑定 - 仅适用于 &lt;select&gt;

<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);
});

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


那该怎么办? -> 阅读文档

查看MDN 上的&lt;option&gt; 文档,我可以看到&lt;option&gt; 具有HTMLOptionElement DOM 接口。该接口应该具有继承自HTMLElement 的所有属性和方法。

HTMLOptionElement 接口表示元素并继承了 HTMLElement 接口的所有属性和方法。 - MDN

所以我想知道,我可以以某种方式将 eventListeners 注册到 &lt;option&gt; 元素吗?

【问题讨论】:

  • 这是一个 X/Y 问题。请解释您的用例,我们可以回答您可能想要的东西,而不是您认为自己想要的东西:)
  • 用例应该很明显。我想在
  • 您将需要使用 select2 或其他一些小部件。您不会在选项上找到好的跨浏览器鼠标悬停触发
  • @D.Schaller 看起来你只能监听由父 &lt;select&gt; 元素本身触发的 change 事件,如果用户改变了它的值。

标签: javascript html vue.js dom-events


【解决方案1】:

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

例如,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>

【讨论】:

  • 听到这个消息很难过。该死。感谢你的信息。因此,要么我制作自己的
  • @D.Schaller - 我意识到我只提到了下拉选择,但非下拉选择的情况略有不同。我已经更新了答案。可能对你的想法没有帮助。 :-)
  • 也许,但不一定。我会让这些信息沉入一段时间,然后重新评估使用非下拉菜单或放弃该功能是否有意义。
猜你喜欢
  • 1970-01-01
  • 2011-12-08
  • 2011-09-21
  • 2022-01-24
  • 2021-12-08
  • 1970-01-01
  • 2010-10-20
相关资源
最近更新 更多