iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0
JavaScript

從PM到前端開發:我的React作品集之旅系列 第 4

Day 4 : 用 SASS 實現 React 主題切換

  • 分享至 

  • xImage
  •  

在之前的文章中,我們介紹了如何利用 CSS Modules 來提升 React 專案的樣式管理,使程式碼更加模組化且易於維護。本篇將更進一步,展示如何整合 SASS 來提升樣式管理效率,並實現應用的動態主題切換功能,讓你的項目具備現代化的外觀和使用體驗。

今天的目標是實現一個可以在 Light Mode(亮色模式)和 Dark Mode(暗色模式)之間切換的應用,並使用全局 SASS 變數來統一管理樣式。透過 React 的 useState,我們可以輕鬆管理這些狀態變化,帶來更加動態且靈活的開發體驗。

day04

CSS Modules 與 SASS:有什麼不同?

在實作之前,我們先簡單比較一下 CSS Modules 和 SASS,幫助你選擇在不同場景下使用合適的工具:

  • CSS Modules:這是一種在 CSS 中實現局部作用域的技術,確保每個模塊的樣式僅影響對應的 React 組件,避免全局樣式污染。這對於大型項目尤其重要,因為它可以讓樣式的管理更加精確且可維護。

  • SASS:SASS 是一種 CSS 的預處理器,提供變數、嵌套、mixin、繼承等功能,使 CSS 更加靈活和易於維護。當你的樣式變得複雜且需要更多可重用的代碼時,SASS 的功能可以顯著提高開發效率。

總結來說,CSS Modules 聚焦於樣式的作用域管理,而 SASS 則提供了強大的語法來優化開發流程。兩者可以結合使用,既能保證樣式隔離,又能利用 SASS 的靈活性來提升可維護性。

在 React 專案中整合 SASS

讓我們開始將 SASS 整合到 React 項目中。首先,安裝 SASS 依賴:

npm install sass -D

接著,更新 webpack.config.js 配置檔,將 .scss 文件納入處理範圍,並添加 sass-loader:

module.exports = {
    // ...其他配置
    module: {
        rules: [
            // ...其他規則
            {
                test: /\.scss$/, // 處理 SASS 文件
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
        ],
    },
};

將你的樣式檔案從 App.module.css 更名為 App.module.scss,並在 App.jsx 中更新引用方式:

import * as styles from "./APP.module.scss";

此時,執行以下命令來進行編譯:

npm run build

如果編譯成功,你的 React 專案已經成功支援 SASS,現在可以靈活使用 SASS 來管理樣式。

實際演練 - 動態主題切換

Step 1: 定義全域 SASS 變數

首先,新增一個 _theme.scss 檔案,定義全域的主題變數,這些變數將在應用中被重複使用,有助於確保樣式的一致性。

/* _theme.scss */
$light-mode-bg: #ffffff;
$light-mode-text: #000000;

$dark-mode-bg: #2e2e2e;
$dark-mode-text: #ffffff;

Step 2: 使用嵌套選擇器優化主題樣式

App.module.scss 中引入_theme.scss,並利用 SASS 的嵌套選擇器來管理不同主題的樣式。這樣,當需要新增或修改主題時,只需更新相關變數,而不必重複撰寫相同的樣式。

/* App.module.scss */

@import './theme';

// ...其他樣式

.appContainer {
    font-family: 'Open Huninn';
    text-align: center;
    padding: 20px;
    transition: background-color 0.3s, color 0.3s;

    &.lightMode {
        background-color: $light-mode-bg;
        color: $light-mode-text;
    }

    &.darkMode {
        background-color: $dark-mode-bg;
        color: $dark-mode-text;
    }
}

// ...其他樣式

這裡使用了 SASS 的嵌套選擇器來針對 .appContainer 元素及其內部狀態(如 .lightMode 和 .darkMode)進行樣式設置。這樣的做法能夠將相關樣式組織在一起,使結構更加清晰,並且便於未來進行主題切換和擴展。

Step 3: 在 useState 進行主題切換

最後,通過 React 的 useState,我們可以追蹤並切換應用的主題狀態。以下是完整的程式碼範例:

import React, { useState } from 'react';
import * as styles from "./APP.module.scss";

const App = () => {
    // 使用 require 導入圖片
    const logoDark = require('@/assets/logo_dark.png');
    const logoLight = require('@/assets/logo_light.png');

    // 使用 useState 管理模式狀態,初始值為 false,表示 Light Mode
    const [isDarkMode, setIsDarkMode] = useState(false)

    const toggleMode = () => {
        setIsDarkMode(!isDarkMode)
    }

    return (
        <div className={`${styles.appContainer}
            ${isDarkMode ? styles.darkMode : styles.lightMode}
            `}>
            <img src={isDarkMode ? logoDark : logoLight}
                alt="Logo" className={styles.img} />
            <h1>歡迎來到熊貓樂園</h1>
            <p>在這裡,我們致力於保護與珍愛熊貓,並與世界分享牠們的故事。</p>
            <button onClick={toggleMode}>
                切換到 {isDarkMode ? 'Light Mode' : 'Dark Mode'}
            </button>
        </div >
    );
};

export default App;

詳解:

  1. isDarkMode:這是應用的狀態變量,用於追蹤當前的主題模式(亮色或暗色)。
  2. setIsDarkMode:這是用於更新 isDarkMode 的函數,當用戶點擊按鈕時,會切換主題。
  3. useState(false):設置應用的初始狀態為亮色模式。

當用戶點擊按鈕時,toggleMode 函數會更新 isDarkMode 的值,進而切換樣式,實現主題的動態變化。

結語

透過將 SASS 與 CSS Modules 結合使用,你可以顯著提升 React 應用的樣式管理效率。此外,動態主題切換功能能夠大幅提升用戶體驗,使你能夠靈活控制不同模式下的外觀樣式。在這篇文章中,我們介紹了如何定義全局變數、使用 SASS 嵌套選擇器進行樣式設置,並運用 useState 實現主題切換的步驟。

如果你想進一步學習或查看完整的範例代碼,歡迎前往 GitHub 專案 react-webpack-starter 的v0.4.0-sass-integration 標籤,這裡提供了 SASS 整合的實際操作範例,幫助你加深對相關概念的理解。希望你能將這些技術應用到實際項目中,打造出更加卓越的應用!

明天,我們將進一步探討如何在多語言應用中實現動態主題切換功能,並展示如何利用 SASS 和 React 一起管理不同主題與語言的樣式變化。

Mixin 與嵌套選擇器有什麼區別?你是否曾經遇到過在不同語言下調整樣式的挑戰?

在下一篇文章中,我們將解答這些問題,並深入探討如何打造真正的國際化應用。


流光館Luma<∕> ✨ 期待與你繼續探索更多技術知識!



上一篇
Day 3 : 整合CSS Modules 提升 React 樣式管理
下一篇
Day 5:整合 i18n,打造多語言 React 應用
系列文
從PM到前端開發:我的React作品集之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言