可构造样式表是一种使用 Shadow DOM 进行创建和分发可重用样式的新方法。
使用 Javascript 来创建样式表是可能的。然而,这个过程在历史上一直是使用 document.createElement(‘style’) 来创建 <style> 元素,然后通过访问其 sheet 属性来获得一个基础的 CSSStyleSheet 实例的引用。这种方法可以生成重复的 CSS,其会使得代码极速膨胀。无论是否存在臃肿,这种附加的动作会导致未样式化内容的闪烁。CSSStyleSheet 接口是 CSS 集合的根,被称为 CSSOM,提供一种程序化的方法去控制样式,还有就是消除相关联的旧代码的问题。
可构造的样式表可以定义和准备共享的 CSS 样式,然后轻松的吧这些样式应用到多个 Shadow Roots 中或者是文档中,且无需重复。修改 CSSStyleSheet 以后,其相关联的样式也都会被改变。并且一旦加载了样式表,其新样式会很快且同步的加载到页面中。
由 Constructable Stylesheets 创建的关联很适合许多不同的应用程序。它可以被用于在多个不同的组件间提供一个集中的主题:主题可以传递到组件的是 CSSStyleSheet 的实例,当主题改变以后,会自动传递给组件。它可以不依赖样式表,吧自定义 CSS 属性分发给特定的 DOM 子树中。它甚至可以直接用于浏览器解析器直接的接口,无需将他们注入到 DOM 就可以很轻易的加载样式表。
构建一个样式表
与引入一个新 API 不同,可构造样式表规范使得其可以通过调用 CSSStyleSheet() 构造函数来强制创建样式表。CSSStyleSheet 对象的结果有两个方法,这俩方法会使样式表更安全的被添加和修改,其操作不会触发无格式内容的闪光(FOUC)。replace() 会返回一个 Promise,一旦有外部引用(@import)被加载就会解析。而 replaceSync() 不允许外部引用。
const sheet = new CSSStyleSheet();// replace all styles synchronously:
sheet.replaceSync(‘a { color: red;}’);// this throws an exception:try {
sheet.replaceSync(‘@import url(“styles.css”)’);} catch (err) {
console.error(err); // imports are not allowed}// replace all styles, allowing external resources:
sheet.replace(‘@import url(“styles.css”)’)
.then(sheet => {
console.log(‘Styles loaded successfully’);
})
.catch(err => {
console.error(‘Failed to load:’, err);
});
使用可构造样式表
由可构造样式表引入的第二个新功能是 Shadow Roots 和 Documents 中的 adoptedStyleSheets 属性。这允许我们显式的将由 CSSStyleSheet 定义的属性应用到给定的 DOM 子树中。为此,我们将属性设置为一个具有一个或者多个样式表的数组,以用于该元素。
// Create our shared stylesheet:const sheet = new CSSStyleSheet();
sheet.replaceSync(‘a { color: red;}’);// Apply the stylesheet to a document:
document.adoptedStyleSheets = [sheet];// Apply the stylesheet to a Shadow Root:const node = document.createElement(‘div’);const shadow = node.attachShadow({mode: ‘open’});
shadow.adoptedStyleSheets = [sheet];
注意我们是覆盖了 adoptedStyleSheets 的值,而不是改变了数组的值。这是必要的,因为这个数组是被冻结的。像 push() 那样改变值会抛出一个异常,所以我们必须赋值一个新数组。为了保留通过 adoptedStyleSheets 添加的已经存在样式表。我们可以使用合并数组的方式来创建一个新数组,这个数组包含已经存在的旧样式,和新添加的新样式。
const sheet = new CSSStyleSheet();
sheet.replaceSync(‘a { color: red;}’);// Combine existing sheets with our new one:
document.adoptedStyleSheets = […document.adoptedStyleSheets, sheet];
总结
由于可构造样式表,网站开发人员现在有一个创建 CSS 样式表并且把他们应用到 DOM 树中的一个明确的解决方案。我们有了一个新的基于 Promise 的 API,用于从使用浏览器内置解析器和加载语义的 CSS 源字符串中加载样式表。最终,我们有一种机制,可以将样式表更新应用于 StyleSheet 的所有用法,从而简化主题更改和颜色首选项等操作。
展望未来
可构建样式表的初始版本附带了此处描述的 API,但正在开展工作以使事情更容易使用。有人建议使用专用方法扩展 adoptStyleSheets FrozenArray 以插入和删除样式表,这样就不需要进行数组克隆并避免可能的重复样式表引用。
翻译自:
https://developers.google.com…