加载Web组件时的事件

时间:2017-08-07 11:07:36

标签: javascript web-component

我有一个像这样的网络组件

<template id="component">
    <link href="/static/css/main.cacbacc7.css" rel="stylesheet">
    <script src="/static/js/vendor.js" type="text/javascript"></script>
    <script src="/static/js/bundle.js" type="text/javascript"></script>
    <span id="react-app"></span>
</template>

<script>
  (function (window, document) {
    const doc = (document._currentScript || document.currentScript).ownerDocument;
    const proto = Object.create(HTMLElement.prototype, {
      attachedCallback: {
        value: function () {
          const template = doc.querySelector('template#component').content;
          const shadowRoot = this.attachShadow({ mode: 'open' });
          shadowRoot.appendChild(template.cloneNode(true));
          // executeThis() when all scripts have been loaded
        }
      },
    });
    document.registerElement('react-webcomponent', { prototype: proto });
  })(window, document);
</script>

我可以知道我的script中的所有template代码都已加载吗?

更新

我目前正在做的是

const scripts = [...shadowRoot.querySelectorAll('script')];
let scriptsLoaded = 0;
scripts.forEach(function (script) {
  script.addEventListener('load', function () {
    if (++scriptsLoaded >= scripts.length) {
      LoadReactAppIntoShadowDomContainer(shadowRoot.querySelector('#react-app'));
    }
  })
});

但我希望有一个更好的方式。

关于可能的重复:它是否适用于Web组件?

2 个答案:

答案 0 :(得分:0)

根据我的理解,截至目前,

  • 您的影子根目录中没有dom onload的事件侦听器

  • 定义自定义元素时,可以在将元素附加到DOM时调用connectedCallback

从你正在尝试的东西,在我看来,你正在试图确定,你的影子DOM加载其内部脚本的确切时间

据我所知,脚本没有作用于你的元素,而且是全局的。

所以,不要试图做你现在正在做的事情,

  • 查询影子Root的DOM结构,收集脚本标签并附加onload,

你可以简单地将一个onload打到一个像往常一样工作的标签上。

此外,如果您想要观察影子DOM的更改,您可能会对mutation observers感兴趣,一旦attached及以后更新。

AFAIK,在构建元素本身/连接之前,您无法观察到DOM更改

或者,如果您要在不同的文件中定义元素,并希望使用HTML Imports将它们导入到文档中,

您可以使用导入文档中的webcomponentsready侦听器,该文件在导入,解析和加载所有DOM时触发

如果确实有办法观察DOM或听取元素的模板附件,我也想知道。

此外,由于您尝试将您的反应应用程序嵌入到自定义元素中,这可能是您知道何时调用loadreactapp函数的问题的原因,您可能需要考虑使用{{1}在你的影子DOM中,它打开你的元素在浏览器上注册后可以分发内容的地方

通过传递属性slots

,只需添加您的应用或其他自定义元素即可

答案 1 :(得分:0)

您的更新示例是我所知道的最佳方式。

我有一个类似的问题,希望在通过标签导入CSS的组件上防止FOUC。

我能找到的唯一解决方案是根据您的更新。 QS使用ShadowRoot查找<link><scripts>,为每个添加加载事件侦听器并比较加载计数。

您可能会考虑的一个优化是,当计数匹配时,您可以从影子根本身调度自己的自定义加载事件,即组件影子根(或树的更上方)上的侦听器可以处理。

var event = new CustomEvent('load');
shadowRoot.dispatchEvent(event);

如果您希望它冒泡并越过阴影边界,则需要将composed : true添加到事件参数中。

var event = new CustomEvent('load', {bubbles : true, composed : true});
shadowRoot.dispatchEvent(event);