ReactCSS作用域

362 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路

抛出问题

众所周知,vue的scoped是为了让css也有独立的作用域,当前组件写的样式只对当前组件的template生效,而在react中我们该如何让css有独立的作用域呢

样式污染的现象及原因

在配置路由时,多个组件都被导入到项目中,那么组件的样式也就被导入到项目中了,也就是说最终的所有的样式文件全汇集到index.html中了。

如果多个组件的样式中出现选择器重复,那么一个组件中的样式就会在另一个组件中也生效,从而造成组件之间样式相互覆盖的问题。

了解css in js解决方案

  • 手动处理: 给每个组件的根元素起不同的类名,确保类名不重复

  • CSS IN JS : 以js的方式来处理css 。通过代码来改动css选择器,让css样式也有局部作用域 全局作用域这样的区分

推荐第二种,即省时又便于后期维护

CSS IN JS

CssModules-基本使用

没有使用

css文件

.root {font-size: 100px;}

jsx文件

import 'index.css'
<div className="root">div的内容</div>

使用后

css文件将XXX.css文件改为XXX.module.css

jsx文件

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

原理

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

示范

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

image.png

CssModules-维持类名

在没有做任何处理的情况下, 每一个类名都会被修改。如果希望某个类名不被修改,可以使用: global

实践

.jsx

import React from 'react';
import styles from './Layout.module.scss'
function Layout(props) {
  return (
    <div className={styles.root}>
      123
<div className={styles.info}>22</div>
      <div className='footer'>32</div>
    </div>
  );
}

export default Layout;

XXX.module.css image.png

优化

最外层使用一个类名然后保证整个module.css的唯一性,然后其他的类名使用global包裹即可,使用起来即实用又便捷

index.module.scss

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

jsx文件

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>
  )
}