17

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

 4 years ago
source link: https://www.zhangxinxu.com/wordpress/2021/02/web-components-import-css/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9816

本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

jMFZBzu.png!mobile

为了重复利用,本文的Web Components组件就使用前两天写的“ 巧用两个type=range input实现区域范围选择 ”这篇文章中的Range组件示意。

原Range组件的CSS都是直接内联在Shadow DOM中的,如下图所示:

NRfURbU.png!mobile

实际开发时候,往往会碰到需要引入外部CSS到Shadow DOM中的情况,此时该如何处理才合适呢?

本文介绍3种处理方法。

假设Range组件需要的CSS都放在了一个名为range.css的文件中。

一、@import方法

代码示意:

class uiRange extends HTMLElement {
    constructor () {
        super();
        // 附加Shadow DOM
        this.attachShadow({
            mode: 'open'
        });
        // 创建样式
        let node = document.createElement('style');
        node.innerHTML = `@import './range.css';`;
        this.shadowRoot.append(node);
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

引用的核心就是下面这样CSS语句:

@import './range.css'

实际DOM渲染效果如下截图(截自Firefox):

VfQ3yq2.png!mobile

优缺点

优点是兼容性不错,支持Shadow DOM的元素均支持此语法;以及使用比较方便。

缺点是性能著名的差。根据我看到的 某些资料的测试数据 ,会有半秒左右的阻塞。

3MFzIfE.png!mobile

不过有些站点对于小小的阻塞延时并不在意,反而更在意使用的便捷性,此时使用@import也是可以的,比方说一些demo原型页面,内部的文档页面等。

如果对性能比较在意,可以试试下面的fetch方法。

二、fetch获取

直接以请求的方式去load CSS文件的资源内容,并在Shadow DOM中输出。

代码示意:

class uiRange extends HTMLElement {
    constructor () {
        super();
        // 附加Shadow DOM
        this.attachShadow({
            mode: 'open'
        });
        // 获取样式
        fetch('./range.css').then(response => response.text()).then(data => {
            let node = document.createElement('style');
            node.innerHTML = data;
            shadow.appendChild(node);
        });
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

由于fetch执行的时候是个异步的过程,因此并不会发生加载阻塞,理论性能会好一点。

优缺点

优点是兼容性不错,支持Shadow DOM的元素均支持此语法;以及性能还OK。

缺点是使用的时候比较啰嗦,也就是语句较多,以及感觉不是很正统。

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9816(作者张鑫旭)

如果从正统角度来说的话,下面的方法是最合适,也是理论上应该推崇的外部CSS引入方法。

三、作为CSS module import

此方法使用浏览器原生的import语法,但是import的是CSS文件而不是JS文件。

也就是把CSS文件直接作为模块引入。

相关代码演示如下:

import styles from './range.css';
class uiRange extends HTMLElement {
    constructor () {
        super();

        let shadow = this.attachShadow({
            mode: 'open'
        });
        shadow.adoptedStyleSheets = [styles];
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

简单的2步:

  1. import引入;
  2. adoptedStyleSheets采用;

这个方法是本文介绍重点,因此有demo,您可以狠狠地点击这里: Web Components中CSS样式import引用demo

说明:由于CSS文件直接import这个语法目前仅Chrome及其同样内核浏览器支持,因此Firefox和Safari下使用的是fetch方法。

关于adoptedStyleSheets

adoptedStyleSheets 这个API方法是随着样式表构造(Constructed StyleSheets)一起出现的。

存在与shadowRoot和document两个对象上,用来设置样式。

例如:

document.adoptedStyleSheets;   // 默认返回 []

adoptedStyleSheets 牵扯到的新的知识点很多,这里不具体展开,以后有机会更详细介绍。

优缺点

优点是使用方便快捷且是官方推荐方法,或者是import CSS模块就是为了这个场景才支持的;以及性能OK,import本身就是异步过程。

缺点就是兼容性不行,如下图(数据源自MDN文档),Firefox和Safari还没有支持。

6ZnUfaV.png!mobile

目前使用还不太成熟,不过现在浏览器支持新特性都是很快的。

说不定2年后就可以用起来了。

其实,配合一些打包工具,实际项目中也是可以使用的。

四、3个方法对比总结

最后,把本文介绍的3个方法再一起对比总结下,参见下表:

性能好 使用便捷 兼容性好 @import ✘ ✔ ✔ fetch ✔ ✘ ✔ import ✔ ✔ ✘

可以发现,缺点每个方法各占一项。

其中,import方法未来最有潜力,因为,兼容性可以慢慢变好,而其他两个方法的缺点已经定型没救了。

大家可以根据实际使用场景选择合适的方法。

以上就是正文内容,感谢你的阅读,行为仓促,如有错误,欢迎指正。

如果觉得文章不错,也欢迎分享。

BnyAV3B.png!mobile

看到上面爱心图标突然想到明天是情人节,哎呀,突然脑壳疼~~

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。

本文地址: https://www.zhangxinxu.com/wordpress/?p=9816

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK