在React以其声明式编程范式和组件化架构,成为了构建用户界面的首选技术之一。然而,随着项目规模的扩大和设计需求的多样化,如何高效地管理 CSS 样式成为了每个React开发者都需要面对的挑战。
本文将从一下三个方面进行介绍,探讨如何在 React 中应用和管理样式,包括内联样式、CSS 类、CSS Modules 和 CSS-in-JS 技术,提升界面美观和开发效率。
在 React 中,组件样式指的是如何为每个独立的组件定义和管理视觉表现。组件样式的设计和应用是 React 开发中的关键部分,它决定了应用的外观和用户体验。
在 React 中,内联样式是一种直接在元素上定义 CSS 样式的方式,类似于在 HTML 中使用 style 属性。不同的是,在 React 中,内联样式是通过一个 JavaScript 对象来定义的,而不是传统的 CSS 字符串。这使得内联样式在 React 中具有更强的动态性和灵活性。
在 React 中,内联样式通过元素的 style 属性来设置,该属性接受一个 JavaScript 对象。对象的键是 CSS 属性名(使用驼峰命名法),值是对应的样式值;如下:
import React from 'react';function InlineStyles() { const divStyle = { color: 'blue', backgroundColor: 'lightgray', padding: '10px', }; return <div style={divStyle}>Hello, World!</div>;}export default InlineStyles;
在这个例子中,divStyle 是一个包含样式属性的 JavaScript 对象,并通过 style 属性应用到 div 元素上。
效果如下:
在 React 的内联样式中,CSS 属性名使用驼峰命名法(camelCase),而不是传统的 CSS 短横命名法(kebab-case)。例如:
内联样式可以非常方便地实现动态样式。你可以根据组件的状态或属性来动态地改变样式。
import React, { useState } from 'react';function DynamicStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; const divStyle = { color: isActive ? 'red' : 'blue', backgroundColor: 'lightgray', padding: '10px', cursor: 'pointer', userSelect: 'none', }; return ( <div style={divStyle} onClick={handleClick}> Click me to change color! </div> );}export default DynamicStyles;
在这个例子中,当点击 div 元素时会切换其文本颜色。效果图如下:
React允许将多个样式对象合并为一个,这在需要应用多个条件样式时非常有用:
const baseStyle = { padding: '10px', margin: '5px' };const activeStyle = { backgroundColor: 'green' };// 合并样式const finalStyle = { ...baseStyle, ...activeStyle };// ...<div style={finalStyle} />
内联样式的优缺点:
优点:
缺点:
与内联样式相比,使用 CSS 类样式可以使代码更清晰、可维护性更高。
/* common.css */.container { color: blue; background-color: lightgray; padding: 10px;}.active { color: red;}
在 React 组件中引入 CSS 文件 在你的 React 组件中,使用 import 语句引入刚刚创建的 CSS 文件:
import { useState } from 'react';import '../assets/styles/common.css';function ClassStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; return ( <div className={`container ${isActive ? 'active' : ''}`} onClick={handleClick}> Click me to change color! </div> );}export default ClassStyles;
可以使用条件渲染的方法动态添加或移除 CSS 类。例如,使用三元运算符或条件运算符:
<div className={`container ${isActive ? 'active' : ''}`} onClick={handleClick}> Click me to change color!</div>
或者,使用 classnames、clsx 库来处理复杂的类名逻辑,下面用 classnames 做个演示:
import { useState } from 'react';import classNames from 'classnames';function ClassnamesStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; return ( <div className={classNames('container', { active: isActive })} onClick={handleClick}> Click me to change color! </div> );}export default ClassnamesStyles;
然后在 App.jsx 中引入 ClassnamesStyles 组件;在这个示例中,classnames 库使得根据条件判断类名的处理更加简洁和易读。效果如下:
为了避免全局样式冲突,React 推荐使用 CSS 模块(CSS Modules),它允许你将 CSS 类名限定在本地作用域内。
/* page.module.css */.container { color: blue; background-color: lightgray; padding: 10px;}.active { color: red;}
在 React 组件中引入和使用 CSS 模块
import { useState } from 'react';import styles from '../assets/styles/page.module.css';function CssModuleStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; return ( <div className={`${styles.container} ${isActive ? styles.active : ''}`} onClick={handleClick}> Click me to change color! </div> );}export default CssModuleStyles;
优缺点对比
优点:
缺点:
在 React 中,Styled Components 和 CSS-in-JS 是用于管理和应用样式的现代解决方案。它们旨在使样式更加模块化、可复用和动态化。
Styled Components 是一个流行的 CSS-in-JS 库,它使用 ES6 的模板字符串语法来定义组件级别的样式。通过使用 Styled Components,你可以将组件的样式与其逻辑紧密结合,使得样式更加模块化和可维护。
$ npm install styled-components
以下是如何在 React 中使用 Styled Components:
import { useState } from 'react';import styled from 'styled-components';// 定义一个带有样式的容器组件const Container = styled.div` /* 根据 props.isActive 设置颜色 */ color: ${props => (props.isActive ? 'red' : 'blue')}; background-color: lightgray; padding: 10px; cursor: pointer; transition: color 0.3s;`;const Button = styled.button` /* 根据 props.primary 设置按钮样式 */ background: ${props => (props.$primary ? '#BF4F74' : 'white')}; color: ${props => (props.$primary ? 'white' : '#BF4F74')}; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid #bf4f74; border-radius: 3px;`;function StyledComponentsStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; return ( <main> <Container isActive={isActive}>Click me to change color!</Container> <Button onClick={handleClick} $primary={isActive}> Primary </Button> </main> );}export default StyledComponentsStyles;
效果如下:
CSS-in-JS 是一种将 CSS 样式直接写在 JavaScript 文件中的技术。Styled Components 是 CSS-in-JS 的实现之一,但还有其他库和方法可以实现 CSS-in-JS,例如 emotion、styled-jsx 等。
优点
缺点
其他 CSS-in-JS 库
$ npm install @emotion/react
在使用 emotion 方案的 jsx 文件开头加入一行 /** @jsxImportSource @emotion/react **/ 的 JSX Pragma(编译指示),告诉 JS 编译器使用 @emotion/react 包来替代 React 原生的jsx 运行时。
/* @jsxImportSource @emotion/react */import React from 'react';import { css } from '@emotion/react';const color = 'white';function EmotionStyles() { return ( <div css={css` padding: 32px; font-size: 16px; background-color: hotpink; font-size: 24px; border-radius: 4px; &:hover { color: ${color}; } `}> Hover to change color. </div> );}export default EmotionStyles;
效果如下:
emotion 也支持了 style-components 的方案,不过要安装一下依赖:npm i @emotion/styled,使用示例如下:
/* @jsxImportSource @emotion/react */import { useState } from 'react';import styled from '@emotion/styled';const Container = styled.div` color: ${props => (props.isActive ? 'red' : 'blue')}; background-color: lightgray; padding: 10px; cursor: pointer; transition: color 0.3s;`;function EmotionStyledStyles() { const [isActive, setIsActive] = useState(false); const handleClick = () => { setIsActive(!isActive); }; return ( <Container isActive={isActive} onClick={handleClick}> Click me to change color! </Container> );}export default EmotionStyledStyles;
效果如下:
Styled Components 和 CSS-in-JS 是现代 React 开发中非常流行的样式解决方案。它们提供了模块化、动态化和高可维护性的样式管理方式。根据项目需求选择合适的方案,可以显著提高开发效率和代码质量。
在 React 项目中,有许多不同的样式管理工具和库可供选择。以下是一些常见的选择:
选择合适的样式管理工具取决于你的项目需求、团队的熟悉度以及具体的使用场景。
原文转自:
https://juejin.cn/post/7384992844191154214