Skip to content

Latest commit

 

History

History
100 lines (74 loc) · 2.44 KB

CSSModules的实现原理.md

File metadata and controls

100 lines (74 loc) · 2.44 KB

# CSS modules的实现原理

CSS 的隔离主要有两类方案,一类是运行时的通过命名区分,一类是编译时的自动转换 CSS,添加上模块唯一标识。

编译时的方案有两种,一种是 scoped,一种是 css modules。

scoped 是 vue-loader 支持的方案,它是通过编译的方式在元素上添加了 data-xxx 的属性,然后给 css 选择器加上[data-xxx] 的属性选择器的方式实现 css 的样式隔离。

比如:

<style scoped> 
.guang { 
    color: red; 
} 
</style>  
<template>  
    <div class="guang">hi</div>  
</template>
复制代码

会被编译成:

<style> 
.guang[data-v-f3f3eg9] 
{ 
    color: red; 
} 
</style> 
<template> 
    <div class="guang" data-v-f3f3eg9>hi</div> 
</template>
复制代码

通过给 css 添加一个全局唯一的属性选择器来限制 css 只能在这个范围生效,也就是 scoped 的意思。

css-modules 是 css-loader 支持的方案,在 vue、react 中都可以用,它是通过编译的方式修改选择器名字为全局唯一的方式来实现 css 的样式隔离。

比如:

<style module> 
.guang {
    color: red; 
} 
</style>  
<template>
    <p :class="$style.guang">hi</p>  
</template>
复制代码

会被编译成:

<style module>
._1yZGjg0pYkMbaHPr4wT6P__1 { 
    color: red; 
} 
</style> 
<template> 
    <p class="_1yZGjg0pYkMbaHPr4wT6P__1">hi</p> 
</template>
复制代码

和 scoped 方案的区别是 css-modules 修改的是选择器名字,而且因为名字是编译生成的,所以组件里是通过 style.xx 的方式来写选择器名。

coped 的方案是添加的 data-xxx 属性选择器,因为 data-xx 是编译时自动生成和添加的,开发者感受不到。

css-modules 的方案是修改 class、id 等选择器的名字,那组件里就要通过 styles.xx 的方式引用这些编译后的名字,开发者是能感受到的。但是也有好处,配合编辑器可以做到智能提示。

此外,除了 css 本身的运行时、编译时方案,还可以通过 JS 来组织 css,利用 JS 的作用域来实现 css 隔离,这种是 css-in-js 的方案。

比如这样:

import styled from 'styled-components';

const Wrapper = styled.div`
    font-size: 50px;
    color: red;
`;

function Guang {
    return (
        <div>
            <Wrapper>内部文件写法</Wrapper>
        </div>
    );
}