当前位置: 首页 > news >正文

React+Ant Design的Layout布局实现暗黑模式切换

目录

  • 效果预览
  • 完整代码
  • 我遇到的BUG
    • 问题代码
    • BUG1:暗黑模式下内容区不变成深色
    • BUG2:光亮模式下的左右区域是深色
  • 补充知识
    • ConfigProvider是什么?
    • Ant Design中的theme如何使用?
      • theme 配置的常见字段
      • 主题算法
      • 通过 useToken 获取主题

效果预览

暗黑模式:
在这里插入图片描述

光亮模式:
在这里插入图片描述

完整代码

import React, { useState } from 'react';
import { Breadcrumb, Layout, Menu, theme, ConfigProvider, Switch } from 'antd';

const { Header, Content, Footer } = Layout;

const items = [{ key: '0', label: '测试' }];

const App: React.FC = () => {
    const [isDarkMode, setIsDarkMode] = useState(false);

    return (
        <ConfigProvider
            theme={{algorithm: isDarkMode ? theme.darkAlgorithm : theme.defaultAlgorithm,}}
        >
            {/* useToken 必须在 ConfigProvider 作用域内 */}
            <ThemeWrapper isDarkMode={isDarkMode} setIsDarkMode={setIsDarkMode} />
        </ConfigProvider>
    );
};

const ThemeWrapper: React.FC<{ isDarkMode: boolean; setIsDarkMode: React.Dispatch<React.SetStateAction<boolean>> }> = ({ isDarkMode, setIsDarkMode }) => {
    const { token } = theme.useToken(); // 确保 useToken 在 ConfigProvider 作用域内

    return (
        <Layout style={{minHeight : window.innerHeight}}>
            <Header
                style={{
                    display: 'flex',
                    alignItems: 'center',
                    background: token.colorBgElevated, // 修正 Header 适配暗黑模式
                }}
            >
                <Menu
                    theme={isDarkMode ? 'dark' : 'light'}
                    mode="horizontal"
                    defaultSelectedKeys={['0']}
                    items={items}
                    style={{
                        flex: 1,
                        minWidth: 0,
                        background: token.colorBgElevated, // 确保 Menu 颜色一致
                    }}
                />
                <div>
                    <Switch
                        checked={!isDarkMode}
                        onChange={() => setIsDarkMode(!isDarkMode)}
                        checkedChildren="🌙"
                        unCheckedChildren="☀️"
                    />
                </div>
            </Header>

            <Content style={{ padding: '0 48px' }}>
                <Breadcrumb
                    style={{ margin: '16px 0' }}
                    items={[{ title: 'Home' }, { title: 'List' }, { title: 'App' }]}
                />
                <div
                    style={{
                        background: token.colorBgContainer, // 确保背景颜色正确
                        color: token.colorText, // 文字颜色适配暗黑模式
                        minHeight: 580,
                        padding: 24,
                        borderRadius: token.borderRadiusLG,
                    }}
                >
                    Content
                </div>
            </Content>

            <Footer style={{ background: token.colorBgElevated, textAlign: 'center' }}>
                Ant Design ©{new Date().getFullYear()} Created by Ant UED
            </Footer>
        </Layout>
    );
};

export default App;

我遇到的BUG

问题代码

import React, { useState } from 'react';
import { Breadcrumb, Layout, Menu, theme, ConfigProvider, Switch } from 'antd';
import './index.css';

const { Header, Content, Footer } = Layout;

const items = [
    {
        key: 0,
        label: '测试',
    },
];

const App: React.FC = () => {
    // 主题切换状态
    const [isDarkMode, setIsDarkMode] = useState(false);

    // 获取当前主题 token(应该在组件顶层调用)
    const { token } = theme.useToken();

    return (
        <ConfigProvider
            theme={{
                algorithm: isDarkMode ? theme.darkAlgorithm : theme.defaultAlgorithm,
            }}
        >
            <Layout>
                <Header style={{ display: 'flex', alignItems: 'center' }}>
                    <Menu
                        theme={isDarkMode ? 'dark' : 'light'}
                        mode="horizontal"
                        defaultSelectedKeys={['0']}
                        items={items}
                        style={{ flex: 1, minWidth: 0 }}
                    />
                    <Switch
                        checked={!isDarkMode}
                        onChange={() => setIsDarkMode(!isDarkMode)}
                        checkedChildren="🌙"
                        unCheckedChildren="☀️"
                    />
                </Header>

                <Content style={{ padding: '0 48px' }}>
                    <Breadcrumb
                        style={{ margin: '16px 0' }}
                        items={[{ title: 'Home' }, { title: 'List' }, { title: 'App' }]}
                    />
                    <div
                        style={{
                            backgroundColor: token.colorBgContainer,
                            minHeight: 1080,
                            padding: 24,
                            borderRadius: token.borderRadiusLG,
                        }}
                    >
                        Content
                    </div>
                </Content>

                <Footer style={{ textAlign: 'center' }}>
                    Ant Design ©{new Date().getFullYear()} Created by Ant UED
                </Footer>
            </Layout>
        </ConfigProvider>
    );
};

export default App;

BUG1:暗黑模式下内容区不变成深色

效果如图:
在这里插入图片描述

原因:theme.useToken() 的 token 在 ConfigProvider 重新渲染时没有立即更新。
解决办法:确保 theme.useToken() 在 ConfigProvider 作用域内,并且 ConfigProvider 重新渲染时 token 正确更新。

BUG2:光亮模式下的左右区域是深色

效果如下:
在这里插入图片描述
产生原因:Header 组件默认没有使用 theme.useToken() 提供的背景色,而是继承了 Ant Design 默认的 light 主题颜色
解决办法:使用 token.colorBgElevated 作为 Header 的背景(它适用于暗黑模式的顶层容器)。确保 Header、Menu、Switch 共享相同的 backgroundColor。

补充知识

ConfigProvider是什么?

ConfigProvider 是 Ant Design 中的一个组件,用于在应用中全局配置和定制 Ant Design 组件的默认行为和主题。它是一个上下文提供器,用来设置应用中的全局配置,比如主题、国际化语言、组件的默认样式等。

Ant Design中的theme如何使用?

在 Ant Design 中,theme 是用于设置和管理 UI 样式的工具,通常与 ConfigProvider 一起使用来定制整个应用的视觉风格。theme 允许开发者通过配置颜色、字体、布局、组件样式等来调整 Ant Design 组件的外观,使其与应用的整体设计保持一致。

theme 配置的常见字段

  • colorPrimary:设置主色调。影响许多组件的颜色,如按钮、链接、选中状态等。
  • colorLink:设置链接文字的颜色。
  • colorBgBase:设置基础背景颜色。
  • colorTextBase:设置基础文字颜色。
  • borderRadiusBase:设置全局组件的边框圆角。
  • fontSizeBase:设置基础字体大小。
  • size:设置默认组件尺寸(如 small, middle, large)。

主题算法

Ant Design 支持多种主题算法,其中常见的包括:

  • theme.defaultAlgorithm:默认主题算法,通常用于浅色模式。
  • theme.darkAlgorithm:暗黑主题算法,用于暗黑模式。

通过 useToken 获取主题

在使用主题时,你可以通过 theme.useToken 来访问当前的主题 token 和样式变量。例如,访问当前主题下的背景色、文本色等:

import React from 'react';
import { theme } from 'antd';

const App: React.FC = () => {
  const { token } = theme.useToken();

  return (
    <div style={{ backgroundColor: token.colorBgContainer, color: token.colorText }}>
      Content with dynamic theme
    </div>
  );
};

export default App;

相关文章:

  • [极客大挑战 2019]Upload_3.19BUUCTF练习day3(2)
  • Ubuntu如何部署AI-Sphere-Butler(metahuman-stream)
  • 23种设计模式-创建型模式-抽象工厂
  • python中两个星号什么意思
  • C#入门学习记录(五)轻松掌握条件分支与循环语句
  • AI+金融 应用 使用DeepSeek、Qwen等大模型输入自然语言,得到通达信等行情软件公式代码,导入后使用
  • 日语学习-日语知识点小记-构建基础-JLPT-N4N5阶段(25):解释说明:という
  • draw.io费的思维导图软件、支持ProcessOn无水印导出。
  • M-LAG 技术全面解析
  • 基于springboot的墙绘产品展示交易平台(037)
  • 进程状态与PV操作
  • Android 13组合键截屏功能的彻底移除实战
  • 数据库MVCC详解
  • Netty——NIO 空轮询 bug
  • 直观理解ECC椭圆曲线加密算法
  • 特征工程自动化(FeatureTools实战)
  • Windows 上彻底卸载 Node.js
  • Linux信号处理:从内核机制到工程艺术
  • nano 是一个简单易用的命令行文本编辑器,适合在终端中快速编辑文件。它比 vi 或 vim 更容易上手,特别适合初学者
  • ES集群的部署
  • 中国女足将于5月17日至6月2日赴美国集训并参加邀请赛
  • 沙县小吃中东首店在沙特首都利雅得开业,首天营业额5万元
  • 水豚“豆包”出逃已40天,扬州茱萸湾景区追加悬赏
  • 宇数科技王兴兴:第一桶金来自上海,欢迎上海的年轻人加入
  • “爱鸟周”为何不能像FI和花展那样“市区联动”
  • 七方面118项任务,2025年知识产权强国建设推进计划印发