阴影 dom 内的脚本无法正常工作
Script inside shadow dom not working
我创建并导出了一个 Angular 元素(Angular 中的 Web 组件)作为单个脚本标签 (user-poll.js)。
要使用此 Angular 元素,我只需要在主机站点中指定以下两行:
<user-poll></user-poll>
<script src="path/to/user-poll.js"></script>
我有以下要求:
- 在外部站点加载多个 Angular 元素。
- 动态加载所有 Angular 元素
我有以下问题:
- 在站点上加载多个组件会产生 Angular 冲突,因为每个组件脚本本身就是一个完整的 Angular 应用程序。
- 为了解决冲突问题,我将每个组件加载到单独的 Shadow Dom 组件中(即在里面添加组件标签和组件脚本文件 link shadow dom 容器)以便每个组件都被沙盒化。但是阴影中的组件脚本 dom 不工作。
JSBin example 动态加载组件内部阴影 dom
<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 元素的最佳方式是什么?
脚本未执行的事实与 Shadow DOM 无关,但与您尝试插入 <script>
元素的方式有关,即通过 [=15= 中的字符串].
在这种情况下,字符串不会被解释,脚本也不会被执行。
如果你想让它工作,你必须通过 appendChild()
插入 <script>
。
您可以通过添加使用 createElement()
创建的 <script>
元素或使用 <template>
元素直接完成此操作。
1.用 createElement()
创建一个 <script>
元素并将其附加到其父元素:
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 )
<div id="elm"></div>
2。带有 <template>
标签
追加 <template>
元素的内容:
elm.attachShadow( { mode: 'open' } )
.appendChild( tpl.content )
<template id="tpl">
<user-poll>
<script>document.write( 'exected' )</script>
</user-poll>
</template>
<div id="elm"></div>
解析 <template>
元素时不执行脚本,但在 content
附加到 DOM.
时执行脚本
PS:无论如何,我不确定这是加载多个 Angular 元素的最佳方式:Shadow DOM 不会作为 Javascript 代码的沙箱,就像 <iframe>
一样。相反,也许你必须使用模块加载器。
我创建并导出了一个 Angular 元素(Angular 中的 Web 组件)作为单个脚本标签 (user-poll.js)。 要使用此 Angular 元素,我只需要在主机站点中指定以下两行:
<user-poll></user-poll>
<script src="path/to/user-poll.js"></script>
我有以下要求:
- 在外部站点加载多个 Angular 元素。
- 动态加载所有 Angular 元素
我有以下问题:
- 在站点上加载多个组件会产生 Angular 冲突,因为每个组件脚本本身就是一个完整的 Angular 应用程序。
- 为了解决冲突问题,我将每个组件加载到单独的 Shadow Dom 组件中(即在里面添加组件标签和组件脚本文件 link shadow dom 容器)以便每个组件都被沙盒化。但是阴影中的组件脚本 dom 不工作。
JSBin example 动态加载组件内部阴影 dom
<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 元素的最佳方式是什么?
脚本未执行的事实与 Shadow DOM 无关,但与您尝试插入 <script>
元素的方式有关,即通过 [=15= 中的字符串].
在这种情况下,字符串不会被解释,脚本也不会被执行。
如果你想让它工作,你必须通过 appendChild()
插入 <script>
。
您可以通过添加使用 createElement()
创建的 <script>
元素或使用 <template>
元素直接完成此操作。
1.用 createElement()
创建一个 <script>
元素并将其附加到其父元素:
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 )
<div id="elm"></div>
2。带有 <template>
标签
追加 <template>
元素的内容:
elm.attachShadow( { mode: 'open' } )
.appendChild( tpl.content )
<template id="tpl">
<user-poll>
<script>document.write( 'exected' )</script>
</user-poll>
</template>
<div id="elm"></div>
解析 <template>
元素时不执行脚本,但在 content
附加到 DOM.
PS:无论如何,我不确定这是加载多个 Angular 元素的最佳方式:Shadow DOM 不会作为 Javascript 代码的沙箱,就像 <iframe>
一样。相反,也许你必须使用模块加载器。