【问题标题】:How to attach a keyup event to Custom Element shadowRoot如何将 keyup 事件附加到自定义元素 shadowRoot
【发布时间】:2019-02-19 03:49:58
【问题描述】:

我已经搜索了一段时间;但只能找到 Polymer 的答案;
或答案将 EventListeners 放置在 shadowRoot 内部的 DOM 元素上。

我尝试使用原生自定义元素实现的效果:

  • 只有焦点元素应该接受(并显示)按键

可以将点击事件附加到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>

【问题讨论】:

  • 我认为你不能在不可聚焦的元素上注册 keyup 事件,除非你用 &lt;div tabindex="0"&gt; 之类的东西来破解它

标签: javascript dom-events addeventlistener shadow-dom custom-element


【解决方案1】:

你可以像以前一样做,但你需要添加一些额外的代码才能让它工作:

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) 最安全的做法是在connectedCallback 中添加eventListener 并在disconnectedCallback 中释放它们,除非您从不打算删除您的组件。

【讨论】:

    【解决方案2】:

    在您的示例中,tabindex 属性设置为自定义元素 &lt;game-toes&gt;,而不是其 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>

    或者,如果您想在 Shadow DOM 级别监听 keyup 事件,您应该在 Shadow DOM 内的元素中设置 tabindex 属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多