这是一些使用 shadowDOM 创建组件的代码。为简单起见,我使用setTimeout 模拟 CSS 的较长加载时间。 1 秒后,我将 CSS 应用到元素中。
正如你所说,在加载 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>
我们可以在 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;
}
.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>
为此,我在 shadow DOM 中设置了顶级元素的 style 标签。我将它设置为display: none; 这隐藏了shadow DOM的内部内容。
然后,1 秒后,加载 CSS 时,它会用 display: block !important 覆盖 display: none;。我必须使用!important 比style 标签中设置的css 更具体。
只有在 CSS 加载后,我的元素才可见。
作为另一种选择,您还可以在您的 <link> 标签上放置一个 onload 事件处理程序:
<link rel="stylesheet" href="mystylesheet.css" onload="sheetLoaded()"
onerror="sheetError()">
这会让您在代码中知道它已加载,然后删除 style 属性。