我正在学习Web组件。在设计自定义元素时,我必须决定在影子DOM中将隐藏什么。然后,其余部分将在轻型DOM中曝光。
据我了解,API允许两个极端的用例,但需要权衡取舍:
由于以下原因,我目前倾向于将所有内容都隐藏在影子DOM中:
我想念什么吗?
编辑
谢谢,我得到答复,这取决于部分回答了我的问题的用例。但是我仍然找不到关于我所处情况的答案:我宁愿不为我的某些组件提供插槽。
我将为频谱的每个极端添加一个示例:
<template id=light-email-view>
<div>
<div><slot name=from></slot></div>
<ul><slot name=to></slot></ul>
<h1><slot name=subject></slot></h1>
<div><slot name=content></slot></div>
<ul><slot name=attachements></slot></ul>
<div class=zero-attachment-fallback>no attachments</div>
</div>
</template>
<template id=shadow-email-view>
<div></div>
</template>
<script>
...
let view = document.createElement('shadow-email-view');
// this method renders the email in the shadow DOM entirely
view.renderFromOject(email);
container.appendChild(view);
</script>
在第一个示例中,组件作者需要做更多的工作,因为他们需要“解析” DOM:他们必须计算附件数量以切换回退。基本上,输入的任何转换(不是浏览器将元素从浅DOM复制到匹配的阴影DOM插槽中)。然后,他们需要监听属性更改等信息。组件用户还需要做更多的工作,他们必须将正确的元素插入正确的插槽中,其中一些是不平凡的(电子邮件内容可能必须链接)。
在第二个示例中,组件作者不需要实现对从带有槽的HTML实例化的支持。但是组件用户必须从JS实例化。 所有渲染由组件作者在
.renderFromObject
方法中完成。如果需要,一些其他方法提供了 Hook 来更新 View 。可以通过让组件同时提供插槽和JS帮助程序来主张中间立场。但是我不明白HTML编写者不打算使用该组件的意义,但还有很多工作要做。
因此,将所有带有影子DOM的东西都设为可行或应该放在我提供的插槽,因为不这样做不符合标准,并且我的代码将破坏某些期望它们的用户代理(忽略那些根本不知道的旧UA)自定义元素)?
最佳答案
@supersharp已将其钉牢。
我对Web组件看到的一件事是,人们倾向于使他们的组件做得太多,而不是分解成较小的组件。
让我们考虑一些本地元素:<form>
没有影子DOM,它唯一要做的就是从其子表单元素中读取值,以便能够进行HTTP GET,POST等操作。<video>
100%shadowDOM,它使用应用程序提供的子代的唯一作用是定义要播放的视频。用户不能为<video>
标记的影子子项调整任何CSS。也不应允许他们这样做。 <video>
标记唯一允许的是隐藏或显示那些影子 child 的能力。 <audio>
标记执行相同的操作。<h1>
到<h6>
没有阴影。这一切都是设置默认字体大小并显示子级。<img>
标记使用阴影子项来显示图像和Alt-Text。
就像@supersharp所说的,shadowDOM的使用是基于元素的。我还要进一步说,shadowDOM应该是一个深思熟虑的选择。我要补充一点,您需要记住,这些应该是组件而不是应用程序。
是的,您可以将整个应用程序封装到一个组件中,但是浏览器并未尝试使用Native组件来做到这一点。您可以使组件变得更加特化,从而使它们变得更可重用。
避免在Web组件中添加非原始JS的任何内容,换句话说,不要在您的组件中添加任何框架代码,除非您永远不想与不使用该框架的人共享它们。我写的组件是100%Vanilla JS,没有CSS框架。它们可以在Angular,React和vue中使用,而无需更改代码。
但是选择对每个编写的组件使用shadowDOM。并且,如果您必须在 native 不支持Web组件的浏览器中工作,则可能根本不想使用shadowDOM。
最后一件事。如果编写的组件不使用shadowDOM但具有CSS,则必须小心放置CSS,因为您的组件可能会放置在其他人的shadowDOM中。如果将CSS放在<head>
标记中,则它将在另一个shadowDOM中失败。我使用以下代码来防止该问题:
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;
关于javascript - 阴影DOM和浅色DOM应该包含哪些部分?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54300456/