react中sass的使用,解决样式污染,样式穿透

4,886 阅读3分钟

sass的使用,解决样式污染,样式穿透

在react脚手架中已经有了sass的配置,因此只需要安装sass的依赖包,就可以直接使用sass了

  • 安装sass依赖包
npm i sass -D

这里的引入文件解决了样式污染问题,以下有详细说明

  • index.css改成index.module.scss
  • 导入import styles from './index.module.scss'文件
使用: ` <div className={styles.css类名}></div>`

注意:如果使用了scss,scss中使用图片的绝对路径的时候需要加上~

background-image: url(~assets/login.png);

css-样式污染

目标

了解样式污染的现象及原因;

了解css in js解决方案

问题引入

如果没有使用css modules在Login组件的index.scss中添加样式

.root {font-size: 100px;}

给Login和Layout组件的根元素都添加.root这个类

发现在Layout组件中的样式也跟着发生了改变。

原因

在配置路由时,Layout和 Login组件都被导入到项目中,那么组件的样式也就被导入到项目中了。如果组件之间选择器重复,那么一个组件中的样式就会在另一个组件中也生效,从而造成组件之间样式相互覆盖的问题。

解决方案

  • 手动处理 (起不同的类名)
  • CSS IN JS : 以js的方式来处理css 。思想是让css有局部作用域全局作用域这样的区分

CSS IN JS

  • 推荐使用:CSS Modules (React脚手架已集成,可直接使用)下面是使用方法:

css modules-基本使用

步骤

  1. 改样式文件名。从 xx.scss -> xx.module.scss (React脚手架中的约定,与普通 CSS 作区分)

  2. 引入使用。

    1. 组件中导入该样式文件(注意语法)

      import styles from './index.module.scss'
      
    2. 通过 styles 对象访问对象中的样式名来设置样式

      <div className={styles.css类名}></div>
      

      css类名是index.module.scss中定义的类名。

示例

原来

  • 定义样式 index.css
.root {font-size: 100px;}
  • 使用样式
import 'index.css'
<div className="root">div的内容</div>

现在

修改文件名: index.css ----> index.module.css。内部不变

使用样式

import styles from './index.module.css'
​
<div className={styles.root}>div的内容</div>

原理

CSS Modules 通过自动给 CSS 类名补足类名,保证类名的唯一性,从而避免样式冲突的问题 。

// Login.jsx
import styles from './index.module.css'
console.log(styles)

image-20211116154129900

css module的注意点

类名最好使用驼峰命名,因为最终类名会生成styles的一个属性

.tabBar {}  ---> styles.tabBar

如果使用中划线的命名,需要使用[]语法-不推荐使用

.tab-bar {}  ---> styles['tab-bar']

cssModules-维持类名

目标

掌握:global关键字的用法,能用它来维持原类名,可以解决样式穿透

格式

在xxx.module.scss中,如果希望维持类名,可以使用格式:

:global(.类名)

示例

这样css modules就不会修改掉类名.a了。等价于写在 index.css中 
:global(.a) {   }
 这样css modules就不会修改掉类名.a了, 但是 .aa还是会被修改 
.aa :golbal(.a) { }

应用:

覆盖第三方组件的样式(样式穿透)

:global(.ant-btn) {
  color: red !important;
}

css modules-最佳实践

  • 每个组件的根节点使用 CSSModules 形式的类名( 根元素的类名: root
  • 其他所有的子节点,都使用普通的 CSS 类名 :global

index.module.scss

// index.module.scss
.root {
  display: 'block';
  position: 'absolute';
  // 此处,使用 global 包裹其他子节点的类名。此时,这些类名就不会被处理,在 JSX 中使用时,就可以用字符串形式的类名
  // 如果不加 :global ,所有类名就必须添加 styles.title 才可以
  :global {
    .title {
      .text {
      }
      span {
      }
    }
    .login-form { ... }
  }
}

组件

import styles from './index.module.scss'
const 组件 = () => {
  return (
    {/* (1) 根节点使用 CSSModules 形式的类名( 根元素的类名: `root` )*/}
    <div className={styles.root}>
      {/* (2) 所有子节点,都使用普通的 CSS 类名*/}
        <h1 className="title">
        <span className="text">登录</span>  
        <span>登录</span>  
      </h1>
            <form className="login-form"></form>
    </div>
  )
}
​