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

web前端开发

共 3843字,需浏览 8分钟

 ·

2021-11-27 10:44

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

01、@import

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

优点:此方法兼容性非常好,点击查看caniuse
缺点:性能

02、::part

::part CSS 伪元素表示在阴影树中任何匹配 part 属性的元素。

示例代码

HTML

<template id="whats-up">    <div part="sup">Sup</div>    <div part="foo">Sup</div></template>
<whats-up></whats-up>

CSS

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

优点:简洁明了
缺点:兼容性不太好,点击查看
caniuse

03、var

CSS自定义属性可以穿透到 Shadow DOM中!
示例代码

js

const template = document.createElement('template');template.innerHTML = `<style>button {  background: var(--background);  color: var(--color);  padding: var(--padding);  font-size: var(--font-size);  border: 0;}</style><div>Sup</div>`;

CSS

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

优点:兼容性好
缺点:比较局限,只能外部定几个,样式不能“自由飞翔”

04、通过属性传入

示例代码

js

class Whatsup extends HTMLElement {  static get observedAttributes() {return ['css']}
constructor() { super(); }
get css() { return this.getAttribute('css'); }
set css(value) { if (value === null || value === false) { this.removeAttribute('css'); } else { this.setAttribute('css', value); } }
connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <style> :host{ display: flex; } ${this.css} // 核心代码 </style> <div>Sup</div> `; }}

HTML

<whats-up  css="    .name{      color: red;    }  "></whats-up>

优点:样式可以随意修改
缺点:代码不够优雅

05、自定义组件内部定义修改样式函数

示例代码

JS

class Whatsup extends HTMLElement {  // ...
// 核心代码 reStyle(els, styles) { const elements = Array.isArray(els) ? els : [els]; elements.forEach((element) => Object.assign(element.style, styles)); }}

HTML

<whats-up></whats-up>
<script> const myEle = document.querySelector('whats-up') const title = myEle.shadowRoot.querySelector('.title');
myEle.reStyle(title, { color: 'red', width: '200px', })</script>

06、通过 slot 外部设置样式

示例代码

JS

class WhatsUp extends HTMLElement {  constructor() {    super();    const shadowRoot = this.attachShadow({ mode: 'open' });    shadowRoot.innerHTML = `    <div>      <slot name="header"></slot>    </div>    `;  }}customElements.define('whats-up', WhatsUp);

HTML

<style>  .header{    color: red;  }</style>
<whats-up> <div slot="header" class="header"> what's up </div></whats-up>

07、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
缺点:不优雅

08、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

总结

各种方法适用场景各不相同,小心食用。


学习更多技能

请点击下方公众号

浏览 28
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报