问题
I have searched for some time; but only find Polymer answers;
or answers where EventListeners are put on DOM elements inside the shadowRoot.
The effect I am trying to achieve with native Custom Elements:
- Only the focussed element should accept (and display) a keypress
It is possible to attach a click event to the shadowRoot, it seems I am doing something wrong for the 'keyup' event.
If I put the EventListener
on the window
all elements (of course) update with the same key info.
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super();
let shadowRoot=this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = this.tabIndex;
shadowRoot.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>
回答1:
You can do it like you were but you need to add some extra code to make it work:
function on(el, evt, cb) {
el.addEventListener(evt, cb);
return () => {
el.removeEventListener(evt, cb);
}
}
window.customElements.define('game-toes', class extends HTMLElement {
constructor() {
super();
let shadowRoot=this.attachShadow({mode: 'open'});
shadowRoot.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>
1) You may want to use evt.stopPropagation()
to stop the event from leaving the component.
2) You either need to add your eventListener on the component itself OR, create an element in the shadowRoot with the ability to take focus and then set focus on the inner element when the component gets focus. And then you should be able to add the keyup
event on that internal element.
3) It is safest to add the eventListener in connectedCallback
and release them in the disconnectedCallback
unless you never plan to remove your component.
回答2:
In your example, the tabindex
attribute is set to the custom element <game-toes>
, and not to its Shadow DOM.
As a consequence, you should instead listen to the keyup
event on the custom element itself :
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>
Alternately, if you want to listen the keyup
event at the Shadow DOM level, you should set the tabindex
attribute in an element inside the Shadow DOM.
来源:https://stackoverflow.com/questions/52330155/how-to-attach-a-keyup-event-to-custom-element-shadowroot