如何将 keyup 事件附加到自定义元素 shadowRoot
How to attach a keyup event to Custom Element shadowRoot
我已经搜索了一段时间;但只能找到 Polymer 答案;
或将 EventListeners 放在 DOM 元素 内部 shadowRoot 中的答案。
我尝试使用原生自定义元素实现的效果:
- 只有焦点元素应该接受(并显示)keypress
可以将点击事件附加到 shadowRoot,看来我对 'keyup' 事件做错了。
如果我将 EventListener
放在 window
上,所有元素(当然)都会更新为相同的密钥信息。
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super().attachShadow({mode:'open'})
.innerHTML = this.tabIndex;
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
在您的示例中,tabindex
属性设置为自定义元素 <game-toes>
,而不是其影子 DOM。
因此,您应该改为监听自定义元素本身的 keyup
事件:
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super();
let shadowRoot=this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = this.tabIndex;
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
或者,如果你想在 Shadow DOM 级别监听 keyup
事件,你应该在 Shadow DOM 内的元素中设置 tabindex
属性.
您可以照原样操作,但需要添加一些额外的代码才能使其正常工作:
function on(el, evt, cb) {
el.addEventListener(evt, cb);
return () => {
el.removeEventListener(evt, cb);
}
}
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super()
.attachShadow({mode: 'open'})
.innerHTML = this.tabIndex;
}
connectedCallback() {
this._offKeyup = on(this, 'keyup', evt => {
this.shadowRoot.innerHTML = evt.key;
evt.stopPropagation(); // Prevent the event from leaving this element
});
}
disconnectedCallback() {
this._offKeyup();
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
- 您可能想使用
evt.stopPropagation()
来阻止事件离开组件。
- 您要么需要在组件本身上添加 eventListener,要么在 shadowRoot 中创建一个能够获得焦点的元素,然后在组件获得焦点时将焦点设置到内部元素。然后您应该能够在该内部元素上添加
keyup
事件。
- 最安全的做法是在
connectedCallback
中添加 eventListener 并在 disconnectedCallback
中释放它们,除非您不打算删除组件。
我已经搜索了一段时间;但只能找到 Polymer 答案;
或将 EventListeners 放在 DOM 元素 内部 shadowRoot 中的答案。
我尝试使用原生自定义元素实现的效果:
- 只有焦点元素应该接受(并显示)keypress
可以将点击事件附加到 shadowRoot,看来我对 'keyup' 事件做错了。
如果我将 EventListener
放在 window
上,所有元素(当然)都会更新为相同的密钥信息。
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super().attachShadow({mode:'open'})
.innerHTML = this.tabIndex;
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
在您的示例中,tabindex
属性设置为自定义元素 <game-toes>
,而不是其影子 DOM。
因此,您应该改为监听自定义元素本身的 keyup
事件:
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super();
let shadowRoot=this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = this.tabIndex;
this.addEventListener('keyup',evt=>this.shadowRoot.innerHTML = 'key:'+evt.key);
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
或者,如果你想在 Shadow DOM 级别监听 keyup
事件,你应该在 Shadow DOM 内的元素中设置 tabindex
属性.
您可以照原样操作,但需要添加一些额外的代码才能使其正常工作:
function on(el, evt, cb) {
el.addEventListener(evt, cb);
return () => {
el.removeEventListener(evt, cb);
}
}
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super()
.attachShadow({mode: 'open'})
.innerHTML = this.tabIndex;
}
connectedCallback() {
this._offKeyup = on(this, 'keyup', evt => {
this.shadowRoot.innerHTML = evt.key;
evt.stopPropagation(); // Prevent the event from leaving this element
});
}
disconnectedCallback() {
this._offKeyup();
}
});
game-toes{
display:inline-block;
height:auto;
width:100px;
padding:1em;
border:10px solid green;
}
game-toes:focus {
background-color: lightgreen;
}
<game-toes tabindex=1></game-toes>
<game-toes tabindex=2></game-toes>
<game-toes tabindex=3></game-toes>
- 您可能想使用
evt.stopPropagation()
来阻止事件离开组件。 - 您要么需要在组件本身上添加 eventListener,要么在 shadowRoot 中创建一个能够获得焦点的元素,然后在组件获得焦点时将焦点设置到内部元素。然后您应该能够在该内部元素上添加
keyup
事件。 - 最安全的做法是在
connectedCallback
中添加 eventListener 并在disconnectedCallback
中释放它们,除非您不打算删除组件。