你听说过 :global 语法吗?

313 阅读2分钟

前段时间在 review 同事代码时,看到他使用了一个我很陌生的语法:global,第一眼看上去有点像是伪类,出于好奇就去了解了下这个语法,通过这篇文章也和大家分享下

关于 :global

大家都知道 css 的规则是全局生效的,即相同的类名都会命中相同的 css 样式规则。而为了解决类名易重复的问题,我们可以借助一些构建工具,将组件的类名转换成唯一的类名

以 webpack 提供的 css-loader 为例:

module.exports = {
    module: {
        rules: [
            {
                test: /.css$/,
                use: ['css-loader'],
                options: {
                    modules: true, // 启用 css 模块
                },
             },
        ]
    }
}

通过 css-loader 可以将类名编译成一个哈希字符串,以达到类名不重复的目的;举例:

编译前:

// index.jsx
import React from 'react';
import style from './App.css';

export default () => {
    return (
        <h1 className={style.title}>
            Hello World
        </h1>
    );
};
/* index.css */
.title {
    color: red;
}

编译后:

// index.jsx
<h1 class="_3zyde4l1yATCOkgn-DBWEL">
    Hello World
</h1>
/* index.css */
._3zyde4l1yATCOkgn-DBWEL {
    color: red;
}

而 :global 语法就是 css 模块提供的一种特殊语法,通过这种方式声明的 class 不会被转换成哈希字符串;举例:

编译前:

.title {
    color: red;
}

:global(.title) {
    color: green;
}

编译后

._3zyde4l1yATCOkgn-DBWEL {
    color: red;
}

.title {
    color: green;
}

那么在什么场景下我们会希望一些类名不被转换呢?

适用场景

对组件样式进行复写

在一些业务场景中,有时我们需要对一些通用的公共组件进行业务的定制化,这种情况下我们一般都会匹配组件的类名并对样式进行改写;举例:

.title {
    & > .antd__menu-title {
        padding: 0;
    }
}

但由于我们开启了 css modules,导致类名会被转换成哈希字符串,使得我们的改写不生效,这种情况下我们就可以通过 :global 语法将组件的类名进行声明,使得这类 class不会被转换,组件的样式就能成功被改写

.title {
    &:global( > .antd__menu-title) {
        padding: 0;
    }
}

其他适用场景还有待补充

参考文章