zoukankan      html  css  js  c++  java
  • react中css作用域问题探究

    场景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的一些常见问题

    • 全局污染
    • 命名混乱
    • 代码关系复杂
    • 无法共享变量
    • 复用性差,难维护

    实现CSS样式隔离的几种方式

    • 行内样式,直接在js中编写css
    • namespaces
    • CSS-in-JS,常见的解决方案有styled-components、styled-jsx、react-style
    • CSS Modules

    行内样式

    优点:

    • 写法简单
    • 优先级高,有类似独立作用域

    缺点:

    • 无法复用
    • 内容与样式没分离,难维护

    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作用域的问题
    • 复用性

    缺点:

    • 一定的学习成本
    • 与常见的写法不同

    CSS Module

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

    效果图:

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

    配置方式:

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

    大功告成!!!

    总结

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

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

    参考

  • 相关阅读:
    微信小程序与Html交互
    vue plupload 的使用
    mac 使用远程连接
    ajax 设置Access-Control-Allow-Origin实现跨域访问
    javascript取模运算是怎么算的?其实是取余数
    [G]Java获取泛型T的类型 T.class
    [G]java反射获得泛型参数getGenericSuperclass()
    Java中的Type类型详解
    利用ParameterizedType获取泛型参数类型
    Type类型详解
  • 原文地址:https://www.cnblogs.com/sk-3/p/14961231.html
Copyright © 2011-2022 走看看