Как прикрепить событие keyup к пользовательскому элементу shadowRoot - PullRequest
0 голосов
/ 14 сентября 2018

Я искал некоторое время; но только найди ответы от Polymer;
или ответы, где EventListeners помещены в элементы DOM внутри shadowRoot.

Эффект, который я пытаюсь достичь с помощью собственных пользовательских элементов:

  • Только сфокусированный элемент должен принимать (и отображать) нажатие клавиши

Возможно прикрепить событие click к shadowRoot, похоже, я что-то не так делаю для события 'keyup'.

Если я поставлю EventListener на window, все элементы (конечно) обновятся с той же ключевой информацией.

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>

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Вы можете сделать это так, как вы, но вам нужно добавить дополнительный код, чтобы он работал:

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) Вы можете использовать evt.stopPropagation(), чтобы остановить событие, покидающее компонент.2) Вам нужно либо добавить свой eventListener на сам компонент, либо создать элемент в shadowRoot с возможностью фокусировки, а затем установить фокус на внутренний элемент, когда компонент получит фокус.И тогда вы сможете добавить событие keyup в этот внутренний элемент.3) Безопаснее всего добавить eventListener в connectedCallback и освободить их в disconnectedCallback, если вы никогда не планируете удалять свой компонент.

0 голосов
/ 14 сентября 2018

В вашем примере атрибут tabindex установлен на пользовательский элемент <game-toes>, а не на его Shadow 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>

В качестве альтернативы, если вы хотите прослушать событие keyup на уровне Shadow DOM, вы должны установить атрибут tabindex в элементе внутри Shadow DOM.

...