【问题标题】:Webcomponents communicating by custom events cannot send data通过自定义事件通信的 Web 组件无法发送数据
【发布时间】:2020-12-17 23:19:17
【问题描述】:

我对 webcomponents 很感兴趣(并且对 javascript 很陌生),我正在尝试建立一个虚拟的微前端应用程序。好的,组件由不同的 Web 服务器(老实说是 webpack devserver)提供服务,并正确显示在“聚合器”页面中。我还添加了一个自定义事件以将一些文本从一个 web 组件发送到另一个,这不起作用。这是发件人 Web 组件:

const tmplt = document.createElement('template');
tmplt.innerHTML = `
<div>
  <label for="sendnpt">message:</label>
  <input id="sendnpt" type="text"></input>
  <button id="sendbtn">Send the message</button>
  <div id="msglog"></div>
</div>
`;

var input = {};

window.customElements.define('team-zero', class TeamZero extends HTMLElement {
  constructor() {
    super();
    this._shadowRoot = this.attachShadow({ 'mode': 'open' });
    this._shadowRoot.appendChild(tmplt.content.cloneNode(true));
    this.button = this._shadowRoot.getElementById('sendbtn');
    input = this._shadowRoot.getElementById('sendnpt');
    this.button.addEventListener('click', function(evt) {
      var msg = {
        bubbles: true,
        detail: {}
      };
      msg.detail.name = input.value;
      console.log('sending msg: ' + JSON.stringify(msg))
      window.dispatchEvent(new CustomEvent('greet', msg));
    });
  }
  connectedCallback() {
    console.log('connected and ready!');
  }
});

这是接收者:

const m = require('mithril');
window.customElements.define('team-one', class TeamOne extends HTMLElement {
  constructor() {
    super();
    this._shadowRoot = this.attachShadow({ 'mode': 'open' });
    window.addEventListener('greet', (msg) => {
      console.log("a message arrives: " + JSON.stringify(msg));
    });
  }
  connectedCallback() {
    console.log('connected!');
    m.mount(this._shadowRoot, {
      view: function(vnode) {
        return m("div", "team-0ne runs mithril!");
      }
    });
  }
});

问题是事件被发出和接收,但其中没有detail。为什么接收器组件无法记录另一个正在发送的文本,我错过了什么?

你可以看到整个虚拟项目here。

【问题讨论】:

    标签: web-component native-web-component


    【解决方案1】:

    与click 等默认事件不同,
    自定义事件需要 composed:true 来“转义”shadowDOM

    注意:除了数据你还可以传递函数引用

    window.customElements.define('my-element', class extends HTMLElement {
        constructor() {
          super().attachShadow({mode:'open'}).innerHTML = `<slot></slot>`;
          
          let report = (evt) =>
            document.body.append(
              document.createElement("br"),
              `${this.id} received: ${evt.type} - detail: ${JSON.stringify(evt.detail)}  `,
              evt.detail.callback && evt.detail.callback(this.id) // not for 'click' event
            );
          
          window.addEventListener('greet', report); // Custom Event
          window.addEventListener('click', report); // button click
            
          this.onclick = () =>
            window.dispatchEvent(new CustomEvent('greet', {
              bubbles: true,
              composed: true,
              detail: {
                fromid: this.id,
                callback: this.callback.bind(this)
              }
            }));
        }
        callback(payload){
          return `${this.id} executed callback function(${payload})`;
        }
      });
    <my-element id=ONE><button>Click One</button></my-element>
    <my-element id=TWO><button>Click Two</button></my-element>

    另见:https://pm.dartus.fr/blog/a-complete-guide-on-shadow-dom-and-event-propagation/

    【讨论】:

    • 您好!谢谢您的回答,我在自定义消息中添加了“composed: true”属性,但没有运气:收到消息(和以前一样)但缺少详细信息。
    • 在您的接收器中,您的msg 是整个JavaScript 事件 所以您想要msg.detail 在线共享代码使用webcomponents.dev
    • 你说得对,我期待 JSON.stringify 也能打印 detail 属性。谢谢!
    猜你喜欢
    • 2022-01-21
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 2016-04-25
    • 2011-03-30
    • 1970-01-01
    相关资源
    最近更新 更多