FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
362 stars 39 forks source link

如何理解用于组件样式覆盖的:global? #253

Open FrankKai opened 3 years ago

FrankKai commented 3 years ago

:global

:global是css-modules的一个概念,用于将当前选择器从局部作用域提升到全局作用域。

:global switches to global scope for the current selector respective identifier

应用场景

举个例子

覆盖ant-design Tab组件的.ant-tabs选择器。

这是antd的默认样式:

.ant-tabs {
    height: 100%,
}
我的组件想要应用的样式(此时没有加:global)
.parent-container {
    .ant-tabs {
        height: 100%,
     }
}

最终渲染结果:

.parent-container_2Uevo7d1cc .ant-tabs_1V-U-7d1cc {
  height: 100%;
}

css modules默认使用的local作用域,因此如果直接添加.ant-tabs,那么css module的编译器会将.ant-tabs认为是组件自定义的class。

最关键的是:我们应用的ant-design的Tab组件,此时它的class名称还是叫.ant-tabs,而不是.ant-tabs_1V-U-7d1cc

所以Tab组件的样式仍然应用原生的.ant-tabs,.ant-tabs_1V-U-7d1cc这个样式规则生成了,但实际上页面上根本没用对应的DOM元素应用这个规则。

我的组件想要应用的样式(此时加了:global)
.parent-container {
    :global {
        .ant-tabs {
            height: 100%,
         }
    }
}

最终渲染结果:

.parent-container_2Uevo7d1cc .ant-tabs {
  height: 100%;
}

通过:global{ ...rules }选择器,可以将花括号中的规则提升为全局作用域(其实也就是不再为花括号中的class生成hash唯一标记)。

例如我们的例子中,ant-design的Tab组件应用的样式是.ant-tabs,而我们生成的规则也正好是.parent-container_2Uevo7d1cc .ant-tabs,并且因为css选择器的权重计算,后者权重更高,因此可以覆盖parent-container_2Uevo7d1cc下的Tab组件的样式规则。

:global会影响到其他组件吗?

为什么要强调parent-container_2Uevo7d1cc呢?因为这个规则会精确作用于parent-container_2Uevo7d1cc下的Tab组件。不会影响其他组件中的Tab组件的样式规则,因为parent-container后面有一串hash。

对于其他组件来说,分两种情况:

没有自定义:global .ant-tabs规则

如果没有自定义:global .ant-tabs规则,那么会默认使用原生的.ant-tabs。

因为如果没有自定义规则的话,在打包出的css文件中,不会生成指向子组件.ant-tabs的规则。

有自定义:global .ant-tabs规则

假设有2个组件,伪代码如下:

parent-containter组件自定义.ant-tabs规则。

<div class="parent-containter">
   <Tabs />
</div>
.parent-container {
    :global {
        .ant-tabs {
            height: 90%,
         }
    }
}

最终生成的规则为:

.parent-container_2Uevo7d1cc .ant-tabs {
  height: 90%;
}

parent-containter-another组件自定义.ant-tabs规则。

<div class="parent-containter-another">
   <Tabs />
</div>
.parent-container-another {
    :global {
        .ant-tabs {
            height: 80%,
         }
    }
}

最终生成的规则为:

.parent-container-another_3fDso13adf .ant-tabs {
  height: 80%;
}

通过最终生成的规则可以看出,2个组件可以生成各自的.ant-tabs规则,因此是互不影响的,不会互相影响。