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

70985692f84990cb9fe3eefc04462626.png

开发中,还是会遇到需要引入外部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。

总结

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

学习更多技能

请点击下方公众号

8ad15172c7ba8da90fed21c41c502441.gif

6a2b2784c1de4770f69b6c88bad068c9.png3bc88ce863346342637fe5191419d7f8.png70fcac10fb5e86fbb8a0761d8060b02c.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值