首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >哪些部分应该放在阴影DOM和轻型DOM中?

哪些部分应该放在阴影DOM和轻型DOM中?
EN

Stack Overflow用户
提问于 2019-01-22 02:30:36
回答 3查看 2.9K关注 0票数 8

我在学习网络组件。在设计自定义元素时,我必须决定隐藏在阴影DOM中的内容。其馀部分将暴露在轻型DOM中。

据我所知,API允许两个极端的用例进行不同的权衡:

  • 在阴影DOM中几乎什么都不隐藏,元素的大部分内容都在轻型DOM中和元素的属性中:
    • 这允许HTML作者在不编写JS的情况下为组件提供显示的任何内容;
    • 这与可搜索性和可访问性的现状非常接近。
    • 但是所涉及的工作几乎没有回报;我增加了组件的复杂性,但是它们没有封装任何东西(所有东西都是公开的)。

  • 在阴影DOM中隐藏几乎所有东西,元素的innerHTML是空的:
    • 这需要从JS实例化元素;
    • 这会更多地锁定使用,因为从JS实例化比使用HTML插槽和属性更严格(按类型划分);
    • 这可能不那么容易搜索和访问(我不确定是否是这样);

目前,我倾向于将所有内容隐藏在阴影DOM中,原因如下:

  • 我打算实例化JS中的所有内容。我不打算手动编写HTML页面。同时编写HTML和JS将是更多的工作。
  • 掩盖一切不是什么认知上的工作。我不需要找到一个正确的平衡,哪些信息是可见的轻DOM。
  • 它更接近于我熟悉的大多数JS框架。

我是不是遗漏了什么?

编辑

谢谢,我的回答是,这取决于用例部分地回答了我的问题。但是,对于我所处的情况,我仍然没有得到一个答案:我宁愿不支持我的一些组件。

我将为每一个极端的光谱添加一个例子:

  • 轻量DOM组件:组件用户必须将元素插入槽中。 无附件
  • 阴影-DOM密集型组件:组件用户必须使用JS。 ..。让view =document.createElement(‘影子电子邮件-视图’);//此方法在阴影DOM中完全呈现电子邮件( email );container.appendChild(视图); 在第一个示例中,组件作者有更多的工作要做,因为他们需要“解析”DOM:他们必须计算附件才能切换回退;基本上,不是浏览器将元素从轻型DOM复制到匹配的阴影DOM槽中的任何输入转换。然后,他们需要侦听属性的变化等等。组件用户也有更多的工作,他们必须将正确的元素插入到正确的插槽中,其中一些是非琐碎的(电子邮件内容可能必须链接)。 在第二个示例中,组件作者不需要实现对从带有槽的HTML中实例化的支持。但是组件用户必须从JS实例化。All呈现由组件作者在.renderFromObject方法中完成。如果需要,一些额外的方法提供钩子来更新视图。 可以通过组件同时提供插槽和JS助手来支持中间立场。但是,如果HTML作者不使用该组件,我看不出有什么意义,这还需要做更多的工作。 所以,是否可以使用影子DOM或提供,因为不这样做是不符合标准的,而且我的代码会破坏一些期望它们的用户代理(忽略那些根本不知道自定义元素的旧UAs )吗?
EN

回答 3

Stack Overflow用户

发布于 2019-01-22 14:49:39

@supersharp已经把它钉死了。

我在Web组件中看到的一件事是,人们倾向于让他们的组件做得太多,而不是分解成更小的组件。

让我们考虑一些本机元素:

<form>没有影子DOM,它所做的唯一的事情就是从其子表单元素中读取值,以便能够执行HTTP、POST等操作。

<video> 100%的shadowDOM和它唯一使用的应用程序提供的孩子是定义什么视频将播放。用户不能为<video>标记的阴影子控件调整任何CSS。也不应该允许他们这样做。<video>标记允许的唯一功能是隐藏或显示这些影子子类。<audio>标记也做同样的事情。

<h1> to <h6>无阴影。所有这一切都是设置一个默认的字体大小和显示子程序。

<img>标记使用阴影子标记来显示图像和Alt-文本。

正如@supersharp所说,shadowDOM的使用是基于元素的。我还要进一步说,shadowDOM应该是一个深思熟虑的选择。我会补充说,你需要记住,这些应该是组件,而不是应用程序。

是的,您可以将整个应用程序封装到一个组件中,但是浏览器并没有尝试使用本机组件。您可以使您的组件变得更可重用。

避免向Web组件中添加任何不是普通JS的内容,换句话说,不要向组件中添加任何框架代码,除非您不想与不使用该框架的人共享这些代码。我编写的组件是100% Vanilla JS,没有CSS框架。他们被用于角度,反应和vue,没有变化的代码。

但是为编写的每个组件选择了使用shadowDOM。而且,如果必须在本机不支持Web组件的浏览器中工作,则可能根本不想使用shadowDOM。

最后一件事。如果您编写的组件不使用shadowDOM,但它有CSS,那么您必须小心放置CSS的位置,因为您的组件可能被放置在其他人的shadowDOM中。如果您的CSS被放置在<head>标记中,那么它将在其他shadowDOM中失败。我使用这段代码来防止这个问题:

代码语言:javascript
复制
function setCss(el, styleEl) {
  let comp = (styleEl instanceof DocumentFragment ? styleEl.querySelector('style') : styleEl).getAttribute('component');
  if (!comp) {
    throw new Error('Your `<style>` tag must set the attribute `component` to the component name. (Like: `<style component="my-element">`)');
  }

  let doc = document.head; // If shadow DOM isn't supported place the CSS in `<head>`
  // istanbul ignore else
  if (el.getRootNode) {
    doc = el.getRootNode();
    // istanbul ignore else
    if (doc === document) {
      doc = document.head;
    }
  }

  // istanbul ignore else
  if (!doc.querySelector(`style[component="${comp}"]`)) {
    doc.appendChild(styleEl.cloneNode(true));
  }
}

export default setCss;
票数 7
EN

Stack Overflow用户

发布于 2019-01-22 08:34:40

选择100%取决于用例。

另外:

  • 如果您希望用户能够用全局CSS样式属性格式化您的自定义元素,您可以选择普通的轻量DOM。
  • 您是对的:在Shadow中,“这可能不太容易搜索”:document.querySelector()方法不会检查Shadow内容。
  • 因此,一些third-pary JS library may fail可以很容易地与影子DOM集成
  • 如果您打算为遗留浏览器使用自定义元素填充,您可能会避免Shadow DOM,因为它的某些功能不能真正填充。
  • 在许多情况下,答案是提供一个混合光DOM和阴影DOM。正如@JaredSmith所建议的:
代码语言:javascript
复制
- Shadow DOM for the Web Component author,
- Light DOM for the Web Compoent user, intergrated in the Shadow DOM with `<slot>`.

最后,您应该考虑使用Web组件来决定是否需要Shadow DOM的上下文。

对编辑的回答

考虑到您的用例,我将创建一个自定义元素,并且:

  • 让用户使用原子值填充轻型DOM :类型元素<div class="mail-to">或自定义子组件<mail-to>,如@Intervalia所建议的,
  • 用阴影DOM来掩盖光DOM,
  • 使用Javascript:this.querySelectorAll('.mail-to')this.querySelectorAll('mail-to')而不是<slot>从轻型DOM中提取数据,并将它们复制(或移动)到Shadow DOM。

这样,用户就不必学习<slot>的工作方式,开发人员将能够以更多的自由格式化web组件的呈现。

代码语言:javascript
复制
<email-view>
  <mail-to>guillaume@stackoverflow.com</mail-to>
  <mail-to>joe@google.fr</mail-to>
  <mail-from>supersharp@cyber-nation.fr</mail-from>
  <mail-body>hello world!</mail-body>
<email-view>
票数 6
EN

Stack Overflow用户

发布于 2019-11-20 18:46:45

这完全取决于你的情况。但是作为一个普遍的规则,如果你发现自己被埋在一个地狱的嵌套阴影根,那么你可以考虑轻松地使用影子王国。如下面的示例所示:

代码语言:javascript
复制
<my-outer-element>
     shadowRoot
       <slot1> ---Reveal dom
       <my-inner-element>
          shadowRoot
                ....
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54300456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档