提问人:McMurphy 提问时间:11/4/2023 最后编辑:McMurphy 更新时间:11/6/2023 访问量:82
如何将 Shadow Dom 与 Javascript 和 CSS 模块一起使用
How to use Shadow Dom with Javascript and CSS modules
问:
编辑 1
非常感谢@Danny提供的非常有用的答案。我想我的问题更多地与 CSS sope 和封装有关。如果我将 CSS 样式表导入模块,那么我不希望该样式表渗入调用者的父级和 lightDOM。我想要达到的效果类似于这个基本的自定义元素:在本例中,我构建了一个 STYLE 元素并将其附加到 HTMLElement 的 Extension 类。
我正在尝试使用 Javascript/CSS 模块实现同样的事情。我将尝试使用 myDiv.part='shadowTree',但这似乎违背了 ShadowDOM 的全部目的。
我会再次阅读 om SLOT,但我只想公开我的模块调用中的某些元素。这就是我认为的 #returnedDiv::p art(styleableRuleException) 是什么,我希望将 CSS 的其余部分强行限定为我的 JS 模块?
WRT MDN 我认为我的问题是我导入的样式表不是“构造样式表”?喜欢:-
let sheet = new CSSStyleSheet();
但是 Web.Dev 说好吗?
<编辑 1
我正在尝试在我的 Javascript 模块中使用 Shadow DOM,并将 CSS 模块/工作表导入 Javascript 模块:-
模块.js
import sheet from '/styles.css' assert {type: 'css'};
export function message()
{
const myDiv = document.createElement("div");
const shadowRoot = myDiv.attachShadow({mode:"open"});
document.adoptedStyleSheets = [sheet];
myDiv.textContent = "This is Text";
return myDiv;
}
一旦我将该行添加到 .attachShadow() 中,DIV“This is Text”的内容就停止出现。
如果我更进一步尝试将样式表采用到 shadowRoot 而不是文档,那么 styles.css 中的 CSS 不会生效。
样式 .css
host:: {
background-color: yellow;
}
div {
background-color: red;
}
我必须做些什么才能在我的模块中使用 Shadow DOM 与 CSS 模块中的采用样式协同使用?
test_mod.html
<!DOCTYPE html>
<html>
<style type="text/css">
div div {
height: 100px;
width: 100px;
text-align: center;
background-color: lightblue;
}
</style>
<script type="module">
import {message} from "http://localhost/message.js";
document.getElementById("demo").appendChild(message());
</script>
<body>
<h1>JavaScript Modules</h1>
<div id="demo"></div>
</body>
</html>
答:
一旦我将该行添加到 .attachShadow() 中,DIV“This is Text”的内容就停止出现。
因为你在 lightDOM 中设置了内容,这些内容只会在你这样做时显示在 shadowDOM 中。<slot>
如果我更进一步尝试将样式表采用到 shadowRoot 而不是文档,那么 styles.css 中的 CSS 不会生效。
语法不是:host
host::
请阅读:
- https://web.dev/articles/constructable-stylesheets
- https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet
这里是一个游乐场,里面有几乎所有的shadowDOM好东西。
JSFiddle:https://jsfiddle.net/WebComponents/bj4n1L0r/
<h1>shadowDOM, loathed but loaded</h1>
<script>
function adoptSheet(atRoot, styles) {
let sheet = new CSSStyleSheet();
sheet.replaceSync(styles);
atRoot.adoptedStyleSheets.push(sheet);
}
// Global CSS
adoptSheet(document, "h1 { background: hotpink }" +
"div { background: pink }" +
"div::part(shadowH1) { background: lightgreen }");
const myDiv = document.createElement("div");
myDiv.setAttribute("border", "true");
const shadowRoot = myDiv.attachShadow({ mode: "open" });
adoptSheet(shadowRoot, ":host { background: red; padding: 5px }" +
":host([border]) { border:2px dashed green }" +
"h1 { color: green }" +
"::slotted(h1) { color: blue }");
myDiv.innerHTML = "<h1 >I am in lightDOM</h1>";
shadowRoot.innerHTML = "<h1 part='shadowH1'>I am in shadowDOM</h1>" +
"<slot>lightDOM will be slotted here</slot>";
document.body.append(myDiv);
</script>
笔记
全局 CSS 样式 BOTH 在主文档中,因为插槽内容不会移动到 shadowDOM 而是反射到 shadowDOM 请参阅(长读):::slotted CSS 选择器用于 shadowDOM
插槽中嵌套的子项<h1>
background:hotpink
::part
在全局 CSS 中可以设置 shadowDOM
中内容的样式 https://developer.mozilla.org/en-US/docs/Web/CSS/::part:host
没有特异性,所以 shadowDOM 不是
这是这样 (web) 组件用户可以覆盖默认样式(参见),如果您不想要,请在 shadowDOM 中添加一个额外的层并设置样式。background: red
background:pink
<div>
有两种类型的(Web 组件)开发人员:
那些抱怨 shadowDOM 的人,以及那些学会掌握 shadowDOM 的人
评论
<slot>
Custom Elements API
shadowDOM
Custom Elements API
<input>, <textarea> etc.
(user-agent) shadowRoot
shadowDOM
我将丹尼的答案标记为正确,因为它包含大量有用的信息。
事实上,我的一个小学生错误是继续将子元素附加到宿主而不是影子根。
顺便说一句。没想到这里有人会年纪大到能记住功夫:-)
评论