xccjk / x-blog

学习笔记
17 stars 2 forks source link

react中css作用域问题探究 #62

Closed xccjk closed 1 year ago

xccjk commented 3 years ago

场景1

新建组件Page1与Page2,两个组件的根节点className设置为一样

目录结构如下:

src/pages/page1/index.js

import React from 'react'
import './index.css'

function Page1() {
  return (
    <div className='title'>page1</div>
  )
}

export default Page1

src/pages/page1/index.css

.title {
  background-color: #ccc;
}

src/pages/page2/index.js

import React from 'react'
import './index.css'

function Page2() {
  return (
    <div className='title'>page2</div>
  )
}

export default Page2

src/pages/page2/index.css

.title {
  background-color: red;
}

src/app.js

import Page1 from './pages/page1';
import Page2 from './pages/page2';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Page1 />
        <Page2 />
      </header>
    </div>
  );
}

export default App;

效果图如下:

会发现两个组件之间样式会相互影响?是因为最终打包出来的样式渲染到节点上是这样的:

结论:CSS文件分离 !== CSS作用域隔离

CSS的一些常见问题

行内样式

优点:

缺点:

src/pages/page5/index.js

import React from 'react'

function Page5() {
  return (
    <div style={{ background: 'red' }}>page5</div>
  )
}

export default Page5

src/pages/page6/index.js

import React from 'react'

function Page6() {
  return (
    <div style={{background: 'green'}}>page6</div>
  )
}

export default Page6

效果图:

namespaces

通过css样式变量的命令来做到作用域隔离 ​ 优点:

缺点:

src/pages/page7/index.js

import React from 'react'
import styles from './index.less'

function Page7() {
  return (
    <div className={styles.page7}>
      page7
      <p>哈哈哈,我是通过namespaces方案区分的</p>
    </div>
  )
}

export default Page7

src/pages/page7/index.less

.page7 {
  background-color: red;
  p {
    font-size: 15px;
    color: #fff;
  }
}

src/pages/page8/index.js

import React from 'react'
import styles from './index.less'

function Page8() {
  return (
    <div className={styles.page8}>
      page8
      <p>哈哈哈,我是通过namespaces方案区分的</p>
    </div>
  )
}

export default Page8

src/pages/page8/index.less

.page8 {
  background-color: #398def;
  p {
    font-size: 30px;
  }
}

效果图:

CSS-in-JS

通过写js的方式来写css,react官方也是推荐这样来写。官方文档CSS-in-JS地址,可以看到常见的基于CSS-in-JS的解决方案 ​ 优点:

缺点:

CSS Module

CSS Module本质是通过三方工具如webpack等,把css的变量唯一化 ​ 效果图: ​

从上面可以看出,我设置的类名为styles.header,但是在经过编译后为indexheader2zovj,其实配置一下css-loader开启css modules即可

配置方式:

{
  test: /\.css$/,
    loader: "style-loader!css-loader?modules"
}

大功告成!!! ​

总结

其实css作用域的本质,就是页面中的类名都是唯一的。现在通过编译工具,可以把页面中类名编译为一个唯一的类名,这样就不会出现类名相同的情况下相互影响。

综合下来,CSS Module会比CSS-in-JS使用起来更方便,对代码的入侵更小,写法也更符合常见的形式,结合三方工具配置起来也挺方便的。