在Web组件中获取事件目标

chr*_*ahl 2 javascript events dom web-component shadow-dom

<a>当用户与Web组件进行交互时,将创建锚元素()。问题是,单击锚点后,无法从Web组件的“外部”返回锚点元素。

我添加了一个事件监听器来document监听点击事件。当单击DOM中某处的元素时,我希望成为e.target被单击的元素。在Web组件内部某处单击的情况下,<fancy-list></fancy-list>将返回自定义元素()-而不是单击的元素。

当影子DOM的模式设置为openDOM时,应该可以访问。

class Fancylist extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });

    const wrapper = document.createElement('div');
    wrapper.innerHTML = `<ul></ul><button>Add item</button>`;

    shadow.appendChild(wrapper);

    this.on_root_click = this.on_root_click.bind(this);
  }

  connectedCallback() {
    this.ul_elm = this.shadowRoot.querySelector('ul');
    this.shadowRoot.addEventListener('click', this.on_root_click, false);
  }

  on_root_click(e){
    switch(e.target.nodeName){
      case 'BUTTON':
        this.ul_elm.innerHTML += '<li><a href="p1">List item</a></li>';
        break;
      case 'A':
        e.preventDefault();
        console.log('You clicked a link!');
        break;
    }
  }
}

customElements.define('fancy-list', Fancylist);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
  <head>
    <title>List</title>
    <meta charset="utf-8" />
    <script type="text/javascript">
      document.addEventListener('DOMContentLoaded', e => {
        document.body.addEventListener('click', e => {
          //console.log(e.composedPath());
          console.log(e.target); // why is this not returning an anchor element when an anchor is clickend inside the <fancy-list>?
        }, false);
      }, false);
    </script>
  </head>
  <body>
  <h1>List</h1>
  <fancy-list></fancy-list>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)

Sup*_*arp 5

Shadow DOM 的目的正是从容器的角度掩盖 HTML内容Shadow DOM。

这就是为什么要重新定位内部事件以公开Shadow DOM主机的原因。

但是,您仍然可以通过获取Event.pathArray属性的第一项来获得实际目标。

event.path[0]
Run Code Online (Sandbox Code Playgroud)

注意:当然,它仅适用于openShadow DOM。

event.path[0]
Run Code Online (Sandbox Code Playgroud)
class Fancylist extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });

    const wrapper = document.createElement('div');
    wrapper.innerHTML = `<ul></ul><button>Add item</button>`;

    shadow.appendChild(wrapper);

    this.on_root_click = this.on_root_click.bind(this);
  }

  connectedCallback() {
    this.ul_elm = this.shadowRoot.querySelector('ul');
    this.shadowRoot.addEventListener('click', this.on_root_click, false);
  }

  on_root_click(e){
    switch(e.target.nodeName){
      case 'BUTTON':
        this.ul_elm.innerHTML += '<li><a href="p1">List item</a></li>';
        break;
      case 'A':
        e.preventDefault();
        break;
    }
  }
}

customElements.define('fancy-list', Fancylist);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答。它在 Firefox 中不起作用,它让我寻找更多答案 - 我发现了这个:/sf/answers/2747194691/ 显然我们对该功能有不同的实现,Event.path 和 Event.composedPath( )。 (2认同)
  • 使用“event.composedPath()”代替“event.path” (2认同)

Copyright Info

© Copyright 2013-2021 admin@qa.1r1g.com

如未特别说明,本网站的内容使用如下协议:
Creative Commons Atution-NonCommercial-ShareAlike 4.0 International license
.

用以下方式浏览
回到顶部