React 中的 CSS

  1. 事实上 CSS 一直是 React 的痛点,也是被很多开发者吐槽、诟病的一个点;
  2. 在组件化中选择合适的 CSS 解决方案应该符合以下条件:
    1. 可以编写局部 CSS,不会随意污染其他组件内的原生;
    2. 可以编写动态的 CSS
    3. 支持所有的 伪类、动画、媒体查询等 CSS 特性;
    4. 编写起来简洁方便、最好符合一贯的 CSS 风格特点;
  3. 在这一点上,Vue 做的要远远好于 React
    1. Vue 通过在 .vue 文件中编写 <style><style> 标签来编写自己的样式;
    2. 通过是否添加 scoped 属性来决定编写的样式是全局有效还是局部有效;
    3. 通过 lang 属性来设置 less、sass 等预处理器;
    4. 通过内联样式风格的方式来根据最新状态设置和改变 css
  4. React 官方并没有给出在 React 中统一的样式风格,有几十种不同的解决方案,上百个不同的库;
  5. 在这篇文章中,会介绍挑选四种解决方案来介绍:
    1. 方案一:内联样式的写法;
    2. 方案二:普通的 CSS 写法;
    3. 方案三:css modules
    4. 方案四:css in js (styled-components)

React 中的 CSS 方案

内联样式

  1. 内联样式是官方推荐的一种 CSS 样式的写法:

    1. style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串;
    2. 可以引用 state 中的状态来设置相关的样式;
    export default class App extends PureComponent {
      constructor(props) {
        super(props);
    
        this.state = {
          titleColor: "red"
        }
      }
    
      render() {
        return (
          <div>
            <h2 style={{color: this.state.titleColor, fontSize: "20px"}}>我是App标题</h2>
            <p style={{color: "green", textDecoration: "underline"}}>我是一段文字描述</p>
          </div>
        )
      }
    }
    
  2. 优点:

    1. 内联样式,样式之间不会有冲突;
    2. 可以动态获取当前 state 中的状态;
  3. 缺点:

    1. 写法上都需要使用驼峰标识;
    2. 某些样式没有提示;
    3. 大量的样式,代码混乱;
    4. 某些样式无法编写 (比如伪类/伪元素)

引入 CSS 样式文件

  1. 普通的 CSS 通常会编写到一个单独的文件,通过 import 引入;

    JSX
    CSS
    import React, { PureComponent } from 'react';
    import './App.css';
    
    export default class App extends PureComponent {
      render() {
        return (
          <div className="app">
            <h2 className="title">我是App的标题</h2>
            <p className="desc">我是App中的一段文字描述</p>
          </div>
        )
      }
    }
    
    .title {
      color: red;
      font-size: 20px;
    }
    
    .desc {
      color: green;
      text-decoration: underline;
    }
    
  2. 这样的编写方式和普通的网页开发中编写方式是一致的:

    1. 如果按照普通的网页标准去编写,那么也不会有太大的问题;
    2. 但是普通的 CSS 都属于全局的 CSS,样式之间会相互影响;

CSS Modules

  1. CSS Modules 并不是 React 特有的解决方案,而是所有使用了类似于 webpack 配置的环境下都可以使用的,React 的脚手架已经内置了 CSS Modules 的配置:

    1. .css/.less/.scss 等样式文件都修改成 .module.css/.module.less/.module.scss 等;
    2. 之后就可以引用并且进行使用了;
  2. CSS Modules 确实解决了局部作用域的问题,但是这种方案也有自己的缺陷:

    1. 所有的 className 都必须使用 {style.className} 的形式来编写;
    2. 不方便动态来修改某些样式,依然需要使用内联样式的方式;
    JSX
    CSS
    import React, { PureComponent } from "react";
    import style from "./1.module.css";
    
    export default class App extends PureComponent {
      render() {
        return (
          <div>
            <h2 className={style.title}>我是标题</h2>
            <h2 className={style['title-2']}>我是标题</h2>
          </div>
        );
      }
    }
    
    .title {
      font-size: 24px;
      color: blue;
    }
    
    .title-2 {
      font-size: 24px;
      color: blue;
    }
    
    /* 可以通过以下方式定义全局样式 */
    :global {
      .global-style {
        color: red;
      }
    }
    

CSS in JS

  1. CSS-in-JS 是指一种模式,其中 CSSJavaScript 生成而不是在外部文件中定义;

  2. 目前比较流行的 CSS-in-JS 的库有哪些呢?

    1. styled-components
    2. emotion
    3. glamorous
  3. 下面开始介绍 styled-components

    1. 安装
      npm install styled-components --save
      
    2. 引入库
      import styled from "styled-components";
      
    3. 定义样式组件
      import React from "react";
      import styled from "styled-components";
      
      // 创建一个 h1 标签组件(styled.标签名)
      const Title = styled.h1`
        font-size: 20px;
        text-align: center;
        color: red;
      `;
      
      export default function App() {
        return <Title>Hello World</Title>;
      }
      
    4. 样式嵌套,可以使用选择器、伪元素、媒体查询以及各类的声明样式
      import React from "react";
      import styled from "styled-components";
      
      const Title = styled.div`
        text-align: center;
          p {
              font-size: 20px;
              color: red;
          }
      `;
      
      export default function App({imgUrl}) {
        return (
          <Title>
              <p>Hello World</p>
          </Title>
        );
      }
      
    5. 创建全局样式
      import { createGlobalStyle } from "styled-components";
      export const GlobalStyle = createGlobalStyle`
      * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
          // background: pink
        }
      `
      
    6. 组件传参
      import React from "react";
      import styled from "styled-components";
      
      const Title = styled.div`
        text-align: center;
          p {
              font-size: 20px;
              color: ${props => props.color};
          }
      `;
      
      export default function App({themeColor}) {
        return (
          <Title>
              <p color={themeColor}>Hello World</p>
          </Title>
        );
      }
      
    7. 样式组件的继承
      const BoringButton = styled.button`
          color: blue;
          background-color: green;
      `;
      
      // 继承 BoringButton 的样式,覆盖自己的 color
      const CoolButton = styled(BoringButton)`
        color: pink;
      `;
      
    8. 使用 css 辅助函数(公共样式)
      import React from "react";
      import styled, {css} from "styled-components";
      
      // 公共样式
      const commonStyle = css`
        color: white;
        font-size: 20px;
      `;
      
      const Button = styled.button`
        ${commonStyle};
        background-color: red;
      `;
      
      const AnotherButton = styled.button`
        ${commonStyle};
        background-color: green;
      `;
      
    9. as 多态属性:可用于更改样式组件的标签类型 (如 div 转为 button,button 转为 a 标签等), 也可传递自定义组件;
      import React, { PureComponent } from "react";
      import styled from "styled-components";
      
      export const Button = styled.button`
        //  background-color: blue;
      `;
      export const NewButton = styled.button`
        background-color: yellow;
      `;
      
      export default class App extends PureComponent {
        render() {
          return (
            <div>
              <Button>我是一个按钮</Button>
              <Button as="a" href="https://www.badiu.com" target="_blank">
                我是使用as修改后的按钮
              </Button>
              <Button as={NewButton}>我是一个新按钮</Button>
            </div>
          );
        }
      }
      
    10. attrs:一种添加属性的方式,只能添加原生标签默认属性,不可自定义属性;
      import React, { PureComponent } from "react";
      import styled from "styled-components";
      
      export const Input = styled.input.attrs({ type: "text", length: (props) => props.length || 10 })`
        background: palevioletred;
        border-radius: 3px;
        border: none;
        color: white;
        padding: ${(props) => props.padding};
      `;
      
      export const PasswordInput = styled(Input).attrs({ type: "password" })`
        background: #8a8a8a;
        length: 300px;
      `;
      
      export default class App extends PureComponent {
        render() {
          return (
            <div>
              <Input length="20" padding="10px"></Input>
              <PasswordInput></PasswordInput>
            </div>
          );
        }
      }
      
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. React 中的 CSS
  2. 2. React 中的 CSS 方案
    1. 2.1. 内联样式
    2. 2.2. 引入 CSS 样式文件
    3. 2.3. CSS Modules
    4. 2.4. CSS in JS