影子dom中的脚本不起作用

Posted

技术标签:

【中文标题】影子dom中的脚本不起作用【英文标题】:Script inside shadow dom not working 【发布时间】:2018-12-08 15:12:00 【问题描述】:

我创建并导出了一个 Angular 元素(Angular 中的 Web 组件)作为单个脚本标签 (user-poll.js)。 要使用这个 Angular Element,我只需要在主机站点中指定以下两行:

 <user-poll></user-poll>
 <script src="path/to/user-poll.js"></script>

Working JSBin Example

我有以下要求:

    在外部站点上加载多个 Angular 元素。 动态加载所有 Angular 元素

我有以下问题:

    在网站上加载多个组件会导致 Angular 冲突,因为每个组件脚本本身就是一个完整的 Angular 应用程序。 为了解决冲突问题,我将每个组件加载到一个单独的 Shadow Dom 组件中(即在 shadow dom 容器中添加组件标记和组件脚本文件链接),以便每个组件都被沙箱化。但是 shadow dom 中的组件脚本不起作用。

shadow dom 内部动态加载组件的JSBin example

<body>

</body>
    setTimeout(() => 
    loadJS();
, 2000);
function loadJS() 
    var elm = document.createElement("div");
    elm.attachShadow(mode: "open");
    elm.shadowRoot.innerhtml = `<user-poll><h2>Custom Web Component - user-poll loaded</h2><script src="https://cdn.rawgit.com/SaurabhLpRocks/795f67f8dc9652e5f119bd6060b58265/raw/d5490627b623f09c84cfecbd3d2bb8e09c743ed4/user-poll.js"><\/\script></user-poll>`;
    document.body.appendChild(elm);

那么,在网站上动态加载多个 Angular 元素的最佳方式是什么?

【问题讨论】:

需要注意的是elm.innerHTML 没有使用ShadowDOM。为此,您需要使用elm.shadowRoot.innerHTML Can scripts be inserted with innerHTML?的可能重复 我的错!将示例更正为正确的 ShadowDOM。 加载脚本的内容也不是为使用 shadow dom 而设计的 【参考方案1】:

脚本未执行的事实与 Shadow DOM 无关,而是与您尝试插入 &lt;script&gt; 元素的方式有关,即通过 innerHTML 中的字符串。 在这种情况下,不会解释字符串,也不会执行脚本。

如果你想让它工作,你必须通过appendChild()插入&lt;script&gt;

您可以直接添加使用createElement() 创建的&lt;script&gt; 元素,或使用&lt;template&gt; 元素。

1.使用 createElement()

创建一个&lt;script&gt; 元素并将其附加到其父元素:

var up = document.createElement( 'user-poll' )
var script = document.createElement( 'script' )
script.textContent = 'document.write( "executed" )'
up.appendChild( script )
elm.attachShadow(  mode: 'open'  )
   .appendChild( up )
&lt;div id="elm"&gt;&lt;/div&gt;

2。带有&lt;template&gt; 标签

追加&lt;template&gt;元素的内容:

elm.attachShadow(  mode: 'open'  )
   .appendChild( tpl.content )
<template id="tpl">
    <user-poll>
        <script>document.write( 'exected' )</script>
    </user-poll>
</template>

<div id="elm"></div>

&lt;template&gt;元素被解析时脚本不会被执行,而是当它的content被追加到DOM时。

PS:无论如何,我不确定这是加载多个 Angular 元素的最佳方式:Shadow DOM 不会像 &lt;iframe&gt; 那样充当 javascript 代码的沙箱。相反,您可能不得不使用模块加载器。

【讨论】:

以上是关于影子dom中的脚本不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Dom-repeat在聚合物2.0中的IE表中不起作用?

脚本中的子进程不起作用,手动启动时会起作用

我在 Unity 中的战斗脚本有点不起作用

Jenkins powershell脚本中的转义空间和解析变量不起作用

为啥 npm install react-router-dom 不起作用?

使用 Find in Awake 缓存脚本引用,在 Start 中不起作用