Shadow DOM:是否可以封装JS?

时间:2015-02-14 16:04:16

标签: javascript html iframe web-component shadow-dom

我正试图找到一种在不使用iframe的情况下封装Javascript的方法。理想情况下,我想要一种在父页面上加载外部HTML组件(小部件)的方法,而不需要使用iframe来加载两步(首先加载主页,然后才加载iframe内容) )。

是否有可能通过一些新的Web组件技术实现这一点 - 影子DOM /模板/导入?我能够接近将HTML添加到shadow DOM并封装CSS,但无法确认是否可以为组件的javascript执行获取单独的文档。

3 个答案:

答案 0 :(得分:4)

通过HTML imports使用的Web组件封装了Shadow DOM HTML 相关脚本。

为了缩小术语范围,我们假设我们有一个聚合物组件core-ajax。这是the code。正如您可能看到的那样,它根本不提供任何HTML标记,仅封装脚本

在主机网页上导入为:

<link 
  rel="import"
  href="https://www.polymer-project.org/components/core-ajax/core-ajax.html"> 

此组件提供了在没有任何JavaScript编码的情况下执行AJAX调用的功能:

<core-ajax
  auto
  url="http://gdata.youtube.com/feeds/api/videos/"
  params='{"alt":"json", "q":"chrome"}'
  handleAs="json"
  response='{{response}}'
</core-ajax>

上面将加载(因为auto属性已设置)指定URL的内容并将响应放入绑定的response变量中。与此组件通信的另一种方法是提供处理程序而不是将模板变量绑定到响应:

  - response='{{response}}'
  + on-core-response="{{handleResponse}}"

可以在页面的javascript中实现handleResponse功能,就是这样。

UPD 虽然目前无法区分主要文档和shadow DOM使用的文档,但在w3c邮件组中这个功能is being discussed将近三年。但是,即使在“我们是否从未在作者空间中完全启用它们”等方面,讨论还远未结束。

答案 1 :(得分:0)

这与影子dom无关,但它与使用javascript完全封装组件有关:https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/

基本上你创建一个iframe节点并将css和javascript注入其中:

var newIframe = document.createElement('iframe')
newIframe.contentWindow.document.open('text/html', 'replace')
var content = '<!DOCTYPE html><html><head>'+CSS+'</head><body>'+HTML+JS+'</body></html>'
newIframe.contentWindow.document.write(content)
newIframe.contentWindow.document.close()

要完全隔离javascript以访问其父页面,我相信您可以使用某种随机生成的域修改父页面document.domain,以便对新的iframe,父页面将看起来像在不同的域中,无法更改其域以匹配。这将伴随所有通常的安全限制。然后你可以通过postmessage安全地与孩子iframe交谈。

理论上,您还可以实现一些通信,根据其内容自动调整iframe元素的大小,模拟非iframe元素in-flow。

这是我想在未来尝试的东西,但还没有尝试过。

答案 2 :(得分:0)

是的,您可以在模板中添加<style><script>代码(代码段仅在支持Shadow DOM的浏览器中运行):

// Create the shadow DOM
var shadow = document.querySelector('#testOutput').createShadowRoot();

// Get the template fragment and add it to the shadow DOM
shadow.appendChild(document.querySelector('#testTemplate').content);
<template id="testTemplate">
  <script>
    alert('Hello from the component');
  </script>
</template>

<div id="testOutput">shadow</div>

或者您可以将它们直接添加到Shadow DOM。

但是,这是currently broken by content security policy and is a high XSS risk