如何将keydown监听器添加到shadow-dom



我一直在尝试为特定web组件的keydown事件实现一个事件侦听器。事件侦听器应该放在web组件中,这样它也可以用于其他项目。我实现了一个onclick监听器,它工作得很好:正在调用两个方法(用于文档和shadow-dom(。但是,这不适用于keydown事件。

我已经做了一些研究,但没有找到合适的解决方案,例如这个。根据该来源,keydown事件应该是";可用的";原样具有CCD_ 1特性。

下面是我的示例代码。这个问题似乎也出现在keyup和keypress事件中。我觉得我错过了一个要点。是否有可能在shadow-dom中处理keydown事件?

class CustomElement extends HTMLElement {
constructor() {
super();
let template = document.getElementById("custom-template");
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
this.shadowRoot.addEventListener("click", (e) => {
alert("click from shadow dom");
});
this.shadowRoot.addEventListener("keydown", (e) => {
e.stopPropagation(); // doesn't seem to change anything 
alert("keydown from shadow dom"); // won't run
});
}
}
window.customElements.define("custom-template", CustomElement);
document.addEventListener("click", (e) => {
alert(`click from document; composed: ${e.composed}`);
});
document.addEventListener("keydown", (e) => {
alert(`keydown from document; composed: ${e.composed}`);
});
<custom-template></custom-template>
<template id="custom-template">
<button>Click me</button>
<div>This is a div</div>
</template>

来源:如何使按键事件的目标等于一个"选择";元素

您的元素没有接收到键盘事件,因为单击时它没有聚焦。单击时,所有元素都无法获得焦点,因为除以下元素外,它们没有设置tabindex焦点标志[来源:www.w3.org/

  • 具有href属性的<a>元素
  • 具有href属性的<link>元素
  • <button>元素
  • 类型属性不处于隐藏状态的<input>元素
  • <select>元素
  • <textarea>元素
  • 编辑主机
  • 浏览上下文容器

如果元素不在焦点中,body元素将接收键盘事件。

当一个元素被聚焦时,文档接收到的关键事件必须针对该元素。可能没有重点元素;当否元素是焦点,文档接收到的关键事件必须针对身体元素[来源:www.w3.org/

通过添加tabindex属性,可以使任何HTML元素都能够接收焦点,从而接收键盘事件。

Web组件shadowDOM示例:

在JSFiddle中表现最佳:https://jsfiddle.net/WebComponents/1muf82nj/

<script>
customElements.define("my-element", class extends HTMLElement {
constructor() {
super().attachShadow({ mode:"open" })
.innerHTML = `<style>
*:focus-within { background:green }
</style>
<button>button</button>
<input>
<div>DIV without tabindex</div>
<div tabindex="0">DIV with tabindex</div>`;
}
connectedCallback() {
const log = (e,t=e.target,n=t.nodeName) => this.shadowRoot.append(
document.createElement("br"),
e.type, e.type=="keydown" ?" key:"+e.key:"" ," in ",  
n=="BODY" ? "e.target=SCRIPT tag!" : t.innerHTML || n);
this.shadowRoot.addEventListener("click", log); // can't do this.shadowRoot.onclick = ...
this.shadowRoot.addEventListener("keydown", log);
document.onkeydown = log;
}
});
</script>
<div><h4>Focus an element, then hit a key</h4></div>
<my-element></my-element>

最新更新