Shadow DOM支持使用<link>
标签加载样式,这些样式的作用方式与使用<style>
声明的样式相同,这非常方便,但附带的问题是样式仅应用于它们已准备就绪,在加载样式时,FOUC无法通过自定义元素的:defined
伪选择器来阻止。我遇到的另一个问题是在构造或连接自定义元素时测量阴影根中的元素,因为在加载和应用样式表之后已知“真实”尺寸,这是我不知道何时会发生的事情(可能是实施后ResizeObserver
会有所帮助吗?)
任何人都可以想出一个聪明的方法来解决这些问题(没有手动或使用构建步骤内联样式)?我的顾虑是否有意义?是否可以将<link rel="stylesheet>
块渲染中的<head>
视为错误,此功能应与此类似?
答案 0 :(得分:1)
如果要避免使用FOUC,则应该隐藏元素,直到应用样式为止。使用fetch
或XMLHttpRequest
或<link onload=...>
时,您可以知道加载样式的时间。
关于维度问题,它并非特定于Shadow DOM,而是CSS体系结构的结果。
无论如何,通常建议设置元素的宽度和高度以避免FOUC,但也要避免整页重绘,以便加快渲染速度。
请注意,Shadow DOM中的<link rel="stylsheet">
支持是非常新的,因此它可能无法在所有浏览器中按预期工作。
答案 1 :(得分:0)
以下是使用shadowDOM创建组件的一些代码。为简单起见,我使用1,2-Dimethylimidazole 1739-84-0 Organic Intermediates, Plastic, Resin & Rubber, Coatings
1,6-Hexanediol 629-11-8 Adhesives & Sealants, Industrial Chemicals, Inks & Digital Inks, Organic Intermediates, Plastic, Resin & Rubber, Coatings
2,2,4-Trimethyl-1,3-Pentanediol Monoisobutyrate 25265-77-4 Inks & Digital Inks, Oil Field Services, Organic Intermediates, Solvents & Degreasers, Coatings
2,6-Dichloroaniline 608-31-1 Agricultural Chemicals, Crop Protection, Organic Intermediates
模拟CSS的长加载时间。 1秒钟后,我将CSS应用到元素中。
正如你所说,元素在加载CSS之前看起来是一种方式。
setTimeout
稍微更改一下,我们可以隐藏元素直到CSS加载:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FOUC Prevention for WC</title>
<script>
var delayedStyles = document.createElement('style');
delayedStyles.textContent = `
:host {
background-color: #DEE;
border: 1px solid #999;
display: block;
width: 400px;
}
h1 {
color: green;
font: 18px/1em Tahoma;
padding: 3px 6px;
}
p {
margin: 5px 10px;
padding: 10px;
}
`;
var template = document.createElement('div');
template.innerHTML = `
<h1>The header</h1>
<p>Some body content</p>
`;
// Class for `<my-component>`
class MyComponent extends HTMLElement {
constructor() {
super();
var sr = this.attachShadow({mode: 'open'});
setTimeout(() => sr.appendChild(delayedStyles.cloneNode(true)), 1000);
sr.appendChild(template.cloneNode(true));
}
}
// Define our web component
customElements.define('my-component', MyComponent);
</script>
</head>
<body>
<my-component></my-component>
</body>
</html>
为此,我在我的shadow DOM中设置了顶级元素的<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>FOUC Prevention for WC</title>
<script>
var delayedStyles = document.createElement('style');
delayedStyles.textContent = `
:host {
background-color: #DEE;
border: 1px solid #999;
display: block;
width: 400px;
}
.innerShell {
display: block !important;
}
h1 {
color: green;
font: 18px/1em Tahoma;
padding: 3px 6px;
}
p {
margin: 5px 10px;
padding: 10px;
}
`;
var template = document.createElement('div');
template.setAttribute('style', 'display: none;');
template.className = 'innerShell';
template.innerHTML = `
<h1>The header</h1>
<p>Some body content</p>
`;
// Class for `<my-component>`
class MyComponent extends HTMLElement {
constructor() {
super();
var sr = this.attachShadow({mode: 'open'});
setTimeout(() => sr.appendChild(delayedStyles.cloneNode(true)), 1000);
sr.appendChild(template.cloneNode(true));
}
}
// Define our web component
customElements.define('my-component', MyComponent);
</script>
</head>
<body>
<my-component></my-component>
</body>
</html>
标记。我将其设置为style
这隐藏了影子DOM的内部内容。
然后,1秒后,当加载CSS时,它会使用display: none;
覆盖display: none;
。我必须使用display: block !important
比!important
标记中的css设置更具体。
只有在CSS加载后,我的元素才会变得可见。
作为其他选项您还可以在style
代码上放置onload
事件处理程序:
<link>
在代码中,您可以通知它已加载,然后只删除<link rel="stylesheet" href="mystylesheet.css" onload="sheetLoaded()"
onerror="sheetError()">
属性。