主题管理使用指南.md 6.0 KB

主题管理使用指南

概述

主题信息已集成到 Redux 状态管理中,可以在任何组件中访问当前主题类型和主题配置。

文件结构

src/
├── states/
│   └── themeSlice.ts          # 主题状态管理
├── themes/
│   ├── lightTheme.ts          # 浅色主题配置
│   ├── darkTheme.ts           # 深色主题配置
│   └── index.ts               # 主题导出
└── app.tsx                    # 主题应用入口

功能特性

1. 主题持久化

  • 主题选择自动保存到 localStorage
  • 刷新页面后保持用户的主题选择
  • 默认主题:深色主题 (dark)

2. 全局访问

  • 任何组件都可以通过 Redux 访问主题信息
  • 支持获取主题类型 ('light' | 'dark')
  • 支持获取完整的主题配置对象

3. 主题切换

  • 提供 setTheme action 设置特定主题
  • 提供 toggleTheme action 在两个主题间切换

在组件中使用主题

方式 1: 获取主题类型(推荐用于条件渲染)

import { useAppSelector } from '@/states/store';

function MyComponent() {
  // 获取当前主题类型
  const themeType = useAppSelector((state) => state.theme.themeType);

  // 根据主题类型动态加载图标
  const iconPath =
    themeType === 'dark' ? '/icons/dark/report.svg' : '/icons/light/report.svg';

  return <img src={iconPath} alt="report" />;
}

方式 2: 获取完整主题配置(推荐用于样式定制)

import { useAppSelector } from '@/states/store';

function MyComponent() {
  // 获取完整的主题配置
  const currentTheme = useAppSelector((state) => state.theme.currentTheme);

  return (
    <div
      style={{
        backgroundColor: currentTheme.token.colorBgContainer,
        color: currentTheme.token.colorText,
        borderColor: currentTheme.token.colorPrimary,
      }}
    >
      内容区域
    </div>
  );
}

方式 3: 同时获取主题类型和配置

import { useAppSelector } from '@/states/store';

function MyComponent() {
  const { themeType, currentTheme } = useAppSelector((state) => state.theme);

  const isDark = themeType === 'dark';

  return (
    <div>
      <p>当前主题: {isDark ? '深色' : '浅色'}</p>
      <div style={{ color: currentTheme.token.colorPrimary }}>主题色文字</div>
    </div>
  );
}

切换主题

方式 1: 设置特定主题

import { useAppDispatch } from '@/states/store';
import { setTheme } from '@/states/themeSlice';

function ThemeSelector() {
  const dispatch = useAppDispatch();

  return (
    <div>
      <button onClick={() => dispatch(setTheme('light'))}>浅色主题</button>
      <button onClick={() => dispatch(setTheme('dark'))}>深色主题</button>
    </div>
  );
}

方式 2: 切换主题

import { useAppDispatch } from '@/states/store';
import { toggleTheme } from '@/states/themeSlice';

function ThemeToggle() {
  const dispatch = useAppDispatch();

  return <button onClick={() => dispatch(toggleTheme())}>切换主题</button>;
}

实际应用场景

场景 1: 根据主题动态加载图标

import { useAppSelector } from '@/states/store';

function ReportIcon() {
  const themeType = useAppSelector((state) => state.theme.themeType);

  // 根据主题类型选择对应的图标路径
  const iconBasePath = `src/assets/Icons/base/module-patient/theme-${themeType}`;

  return (
    <img src={`${iconBasePath}/1x/report.svg`} alt="report" className="icon" />
  );
}

场景 2: 主题感知的组件样式

import { useAppSelector } from '@/states/store';

function Card({ children }) {
  const { themeType, currentTheme } = useAppSelector((state) => state.theme);

  return (
    <div
      className={`card card-${themeType}`}
      style={{
        backgroundColor: currentTheme.token.colorBgContainer,
        borderColor: currentTheme.token.colorPrimary,
        color: currentTheme.token.colorText,
      }}
    >
      {children}
    </div>
  );
}

场景 3: 条件渲染不同的组件

import { useAppSelector } from '@/states/store';

function ThemedLogo() {
  const themeType = useAppSelector((state) => state.theme.themeType);

  return themeType === 'dark' ? <DarkLogo /> : <LightLogo />;
}

可用的主题 Token

常用颜色 Token

currentTheme.token.colorPrimary; // 主色调
currentTheme.token.colorBgContainer; // 容器背景色
currentTheme.token.colorBgLayout; // 全局背景色
currentTheme.token.colorText; // 文字颜色
currentTheme.token.buttonBgHover; // 按钮悬停背景色

浅色主题 (lightTheme)

  • colorPrimary: #1DA57A
  • colorBgContainer: #FFFFFF
  • colorText: #000000
  • colorBgLayout: #FAFAFA

深色主题 (darkTheme)

  • colorPrimary: #1DA57A
  • colorBgContainer: #1F1F1F
  • colorText: #E0E0E0
  • colorBgLayout: #121212

类型定义

// 主题类型
type ThemeType = 'light' | 'dark';

// 主题配置类型
type ThemeConfig = typeof lightTheme;

// Redux 状态中的主题状态
interface ThemeState {
  themeType: ThemeType;
  currentTheme: ThemeConfig;
}

最佳实践

  1. 优先使用主题类型判断: 对于简单的条件渲染(如图标切换),直接使用 themeType 即可
  2. 使用主题配置定制样式: 需要精确控制样式时,使用 currentTheme.token 中的值
  3. 避免硬编码颜色: 所有颜色都应该从主题配置中获取,确保主题切换时样式一致
  4. 组件解耦: 不要在组件内部导入 lightThemedarkTheme,始终从 Redux 获取

注意事项

  • 主题切换是全局的,会影响所有使用 Ant Design ConfigProvider 的组件
  • CSS 变量已自动注入到 :root,可在 Tailwind CSS 中使用
  • 主题信息会自动保存到 localStorage,无需手动处理
  • 默认主题为深色主题 (dark)

调试技巧

在浏览器控制台中查看当前主题状态:

// 在开发环境中,store 已暴露到 window
window.store.getState().theme;