Web|Web Components中引入外部CSS的 8 种方法

开发中,还是会遇到需要引入外部CSS到Shadow DOM情况,那么如何处理呢?作者就最近遇到的情况给出如下几种方案。
一、@import 示例代码

const template = document.createElement('template'); class WhatsUp extends HTMLElement { connectedCallback() { const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innderHTML = `@import "./index.css"; // 核心代码Sup ` } }window.customElements.define('whats-up', WhatsUp);

优点:此方法兼容性非常好,点击查看caniuse。
缺点:性能
二、::part ::part CSS 伪元素表示在阴影树中任何匹配 part 属性的元素。
示例代码
HTML

CSS
whats-up::part(sup) { /* 样式作用于 `sup` 部分 */ } whats-up::part(foo) { /* 样式作用于 `foo` 部分 */ }

优点:简洁明了
缺点:兼容性不太好,点击查看caniuse。
三、var CSS自定义属性可以穿透到 Shadow DOM中!
示例代码
JS
const template = document.createElement('template'); template.innerHTML = `button { background: var(--background); color: var(--color); padding: var(--padding); font-size: var(--font-size); border: 0; }Sup`;

CSS
whats-up { --background: #1E88E5; --color: white; --padding: 2rem 4rem; --font-size: 1.5rem; }

优点:兼容性好
缺点:比较局限,只能外部定几个,样式不能“自由飞翔”
四、通过属性传入 示例代码
JS
class Whatsup extends HTMLElement { static get observedAttributes() {return ['css']}constructor() { super(); }get css() { return this.getAttribute('css'); }set css(value) { if (value =https://www.it610.com/article/== null || value === false) { this.removeAttribute('css'); } else { this.setAttribute('css', value); } }connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = `:host{ display: flex; } ${this.css} // 核心代码Sup `; } }

HTML

优点:样式可以随意修改
缺点:代码不够优雅
五、自定义组件内部定义修改样式函数 示例代码
JS
class Whatsup extends HTMLElement { // ...// 核心代码 reStyle(els, styles) { const elements = Array.isArray(els) ? els : [els]; elements.forEach((element) => Object.assign(element.style, styles)); } }

HTML

六、通过 slot 外部设置样式 示例代码
JS
class WhatsUp extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ``; } } customElements.define('whats-up', WhatsUp);

HTML
.header{ color: red; }what's up

七、fetch获取
示例代码
class WhatsUp extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); // 获取样式 fetch('./index.css').then(res => res.text()).then(data => { let node = document.createElement('style'); node.innerHTML = data; this.shadowRoot.appendChild(node); }); // ... } } customElements.define('whats-up', WhatsUp);

优点:优点是兼容性不错,支持Shadow DOM的元素均支持此语法;以及性能还OK
缺点:不优雅
八、CSS module import 此方法使用浏览器原生的import语法,但是import的是CSS文件而不是JS文件。
也就是把CSS文件直接作为模块引入。
示例代码
import styles from "index.css"; class WhatsUp extends HTMLElement { constructor() { // ... // 核心代码 shadow.adoptedStyleSheets = [styles]; } }

优点:优点是使用方便快捷且是官方推荐方法,或者是import CSS模块就是为了这个场景才支持的;以及性能OK,import本身就是异步过程。
缺点:兼容性不佳,狠狠戳这里caniuse。
总结 【Web|Web Components中引入外部CSS的 8 种方法】各种方法适用场景各不相同,小心食用。

    推荐阅读