大家好,我是長林啊!一個愛好 JavaScript、Go、Rust 的全棧開發者;致力於終生學習和技術分享。
在React以其聲明式編程範式和組件化架構,成為了構建用户界面的首選技術之一。然而,隨着項目規模的擴大和設計需求的多樣化,如何高效地管理 CSS 樣式成為了每個React開發者都需要面對的挑戰。
本文將從一下三個方面進行介紹,探討如何在 React 中應用和管理樣式,包括內聯樣式、CSS 類、CSS Modules 和 CSS-in-JS 技術,提升界面美觀和開發效率。
常見的樣式方案
在 React 中,組件樣式指的是如何為每個獨立的組件定義和管理視覺表現。組件樣式的設計和應用是 React 開發中的關鍵部分,它決定了應用的外觀和用户體驗。
內聯樣式 (Inline Styles)
在 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 元素上。
效果如下:
<img src="https://files.mdnice.com/user/8213/24516572-c842-4d4f-8c16-8078892b9c4e.png" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
樣式屬性的命名
在 React 的內聯樣式中,CSS 屬性名使用駝峯命名法(camelCase),而不是傳統的 CSS 短橫命名法(kebab-case)。例如:
background-color在 React 中寫成backgroundColorfont-size寫成fontSizemargin-top寫成marginTop
動態樣式
內聯樣式可以非常方便地實現動態樣式。你可以根據組件的狀態或屬性來動態地改變樣式。
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 元素時會切換其文本顏色。效果圖如下:
<img src="https://files.mdnice.com/user/8213/cee5817c-04da-4b6e-9852-e13bb05d2ce0.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
樣式合併
React允許將多個樣式對象合併為一個,這在需要應用多個條件樣式時非常有用:
const baseStyle = { padding: '10px', margin: '5px' };
const activeStyle = { backgroundColor: 'green' };
// 合併樣式
const finalStyle = { ...baseStyle, ...activeStyle };
// ...
<div style={finalStyle} />
內聯樣式的優缺點:
優點:
- 局部作用域:內聯樣式只作用於當前的元素,不會影響其他元素,避免了樣式衝突。
- 動態性:可以很方便地根據組件的狀態或屬性來動態設置樣式。
- 簡潔:對於簡單的樣式,可以減少代碼量和文件數量。
缺點:
- 可維護性:當樣式變得複雜時,內聯樣式會使得組件代碼變得難以維護。
- 複用性差:內聯樣式無法複用,相同的樣式需要在多個地方重複定義。
- 缺少偽類和偽元素支持:內聯樣式無法直接使用 CSS 偽類和偽元素(如 :hover, ::after)。
- 性能差:聯樣式對象包含大量的屬性或者嵌套的對象,這可能會使得樣式對象的創建和合並更加耗時。
CSS 類 (CSS Classes)
與內聯樣式相比,使用 CSS 類樣式可以使代碼更清晰、可維護性更高。
使用 CSS 類樣式的基本方法
-
創建 CSS 文件
首先,你需要創建一個 CSS 文件,並在其中定義你的 CSS 類。例如,創建一個 common.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;在這個示例中,我們使用模板字符串(template literals)來動態添加或移除 CSS 類。效果如下:
<img src="https://files.mdnice.com/user/8213/6e9433f3-653b-4701-b9ff-08989882f0d8.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
動態添加或移除 CSS 類
可以使用條件渲染的方法動態添加或移除 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 庫使得根據條件判斷類名的處理更加簡潔和易讀。效果如下:
<img src="https://files.mdnice.com/user/8213/191cfe99-2cbd-43a1-b36a-93160f13b5d9.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
CSS Modules
為了避免全局樣式衝突,React 推薦使用 CSS 模塊(CSS Modules),它允許你將 CSS 類名限定在本地作用域內。
-
創建 CSS 模塊文件
首先,創建一個 CSS 模塊文件,例如 page.module.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;在這個示例中,CSS 類名是通過 styles 對象來引用的,這樣可以確保類名在本地作用域內不發生衝突。
優缺點對比
優點:
- 可維護性高:樣式定義集中在一個地方,使得代碼更清晰易讀。
- 複用性好:相同的樣式可以在多個組件中複用。
- 避免衝突:使用 CSS 模塊可以避免全局命名衝突。
缺點:
- 動態性較差:相比於內聯樣式,動態設置樣式略顯不便。
- 額外的構建步驟:需要引入和配置 CSS 文件,增加了項目的構建複雜度。
Styled Components 和 CSS-in-JS
在 React 中,Styled Components 和 CSS-in-JS 是用於管理和應用樣式的現代解決方案。它們旨在使樣式更加模塊化、可複用和動態化。
Styled Components
Styled Components 是一個流行的 CSS-in-JS 庫,它使用 ES6 的模板字符串語法來定義組件級別的樣式。通過使用 Styled Components,你可以將組件的樣式與其邏輯緊密結合,使得樣式更加模塊化和可維護。
-
安裝 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;
效果如下:
<img src="https://files.mdnice.com/user/8213/b3ac380e-1237-4434-a043-f2e1258e3f35.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
CSS-in-JS
CSS-in-JS 是一種將 CSS 樣式直接寫在 JavaScript 文件中的技術。Styled Components 是 CSS-in-JS 的實現之一,但還有其他庫和方法可以實現 CSS-in-JS,例如 emotion、styled-jsx 等。
優點
- 模塊化:每個組件的樣式都與組件本身緊密結合,避免了樣式衝突。
- 動態樣式:可以方便地根據組件的狀態或屬性來動態調整樣式。
- 可維護性:將組件的樣式和邏輯放在一起,使得代碼更加內聚和可維護。
- 自動前綴:自動添加瀏覽器前綴,使得樣式兼容更多瀏覽器。
缺點
- 性能:在某些情況下,CSS-in-JS 可能會對性能產生影響,因為樣式是在運行時生成的。
- 學習曲線:需要學習新的庫和語法,可能增加項目的複雜性。
其他 CSS-in-JS 庫
- Emotion
Emotion 是另一個流行的 CSS-in-JS 庫,具有強大的動態樣式和高性能的特點。 -
安裝 Emotion
$ 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;效果如下:
<img src="https://files.mdnice.com/user/8213/a9fd13b0-5a57-4b32-b73a-9cafdb204ddf.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
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;
效果如下:
<img src="https://files.mdnice.com/user/8213/4d0c16f4-0cdc-474a-ae35-fc55183b2bc1.gif" style="border:1px solid rgb(222, 198, 251);border-radius: 8px" />
Styled Components 和 CSS-in-JS 是現代 React 開發中非常流行的樣式解決方案。它們提供了模塊化、動態化和高可維護性的樣式管理方式。根據項目需求選擇合適的方案,可以顯著提高開發效率和代碼質量。
總結
在 React 項目中,有許多不同的樣式管理工具和庫可供選擇。以下是一些常見的選擇:
- CSS-in-JS:Styled Components, Emotion
- Utility-First CSS 框架:Tailwind CSS、unocss
- 組件庫:Bootstrap (react-bootstrap), Ant Design, Material-UI等
- CSS 預處理器:Sass、less
- CSS 模塊:CSS Modules
選擇合適的樣式管理工具取決於你的項目需求、團隊的熟悉度以及具體的使用場景。
上面的代碼均可以在 clin211/react-awesome 中找到,傳送門。
本文首發在我的微信公眾號【長林啊】,歡迎大家關注、分享、點贊!