Ant design v4中如何动态切换主题?

J V*_*J V 16 css less reactjs antd

我想使用 Ant design v4动态实现暗/亮主题之间的切换

可以使用其他 CSS/LESS 导入自定义主题,如此处所述:https : //ant.design/docs/react/customize-theme#Use-dark-theme

但我不确定如何从代码中动态地在这些主题之间切换。我的 React 应用程序 ( darkMode) 中有一个变量,用于指示当前是否使用了深色主题。更改此变量时,我必须提供正确的 CSS 文件。但是我不能仅在满足某些条件时动态导入 CSS,因为这不是导入的工作方式。

我试图require在下面的代码中做一些乱七八糟的事情,但这是非常非常糟糕的方法,它仍然无法正常工作(因为 CSS 被注入但可能没有被撤回。):

const Layout = () => {
  ...
  useEffect(() => {
    if (darkMode === true) {
      require("./App.dark.css")
    } else {
      require("./App.css")
    }
  }, [darkMode])

  return (
    <Home />
  )
}
Run Code Online (Sandbox Code Playgroud)

应该可以以某种方式切换主题,因为它已经在 Ant 设计文档 ( https://ant.design/components/button/ ) 中实现:

Antd 文档中的主题切换

你知道怎么做吗?

谢谢!

kee*_*ahs 5

这就是我现在正在使用的 -

PS-

  1. 我不知道这是否会产生最佳的捆绑尺寸。
  2. 更改主题会导致页面重新加载。

创建一个名为“themes”的文件夹 - 它将有 6 个文件 -> dark-theme.css、dark-theme.jsx、light-theme.css、light-theme.jsx、use-theme.js、theme-provider.jsx 。下面对它们中的每一个进行描述。


深色主题.css

import "~antd/dist/antd.dark.css";
Run Code Online (Sandbox Code Playgroud)

黑暗主题.jsx

import "./dark-theme.css";
const DarkTheme = () => <></>;
export default DarkTheme;
Run Code Online (Sandbox Code Playgroud)

浅色主题.css

@import "~antd/dist/antd.css";
Run Code Online (Sandbox Code Playgroud)

浅色主题.jsx

import "./light-theme.css";
const LightTheme = () => <></>;
export default LightTheme;
Run Code Online (Sandbox Code Playgroud)

use-theme.js不同组件可以使用的自定义挂钩-

import { useEffect, useState } from "react";

const DARK_MODE = "dark-mode";

const getDarkMode = () => JSON.parse(localStorage.getItem(DARK_MODE)) || false;

export const useTheme = () => {
  const [darkMode, setDarkMode] = useState(getDarkMode);

  useEffect(() => {
    const initialValue = getDarkMode();
    if (initialValue !== darkMode) {
      localStorage.setItem(DARK_MODE, darkMode);
      window.location.reload();
    }
  }, [darkMode]);

  return [darkMode, setDarkMode];
};
Run Code Online (Sandbox Code Playgroud)

主题提供者.jsx

import { lazy, Suspense } from "react";
import { useTheme } from "./use-theme";

const DarkTheme = lazy(() => import("./dark-theme"));
const LightTheme = lazy(() => import("./light-theme"));

export const ThemeProvider = ({ children }) => {
  const [darkMode] = useTheme();

  return (
    <>
      <Suspense fallback={<span />}>
        {darkMode ? <DarkTheme /> : <LightTheme />}
      </Suspense>
      {children}
    </>
  );
};
Run Code Online (Sandbox Code Playgroud)

将index.js更改为-

ReactDOM.render(
  <React.StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
Run Code Online (Sandbox Code Playgroud)

现在,在我的导航栏中假设我有一个开关来切换主题。这就是它的样子 -

const [darkMode, setDarkMode] = useTheme();
<Switch checked={darkMode} onChange={setDarkMode} />
Run Code Online (Sandbox Code Playgroud)


Bru*_*uce -3

  1. 在运行时使用较少的编译器:
    https://medium.com/@mzohaib.qc/ant-design-dynamic-runtime-theme-1f9a1a030ba0

  2. 将 less 代码导入包装器
    https://github.com/less/less.js/issues/3232

.any-scope {
    @import url('~antd/dist/antd.dark.less');
}
Run Code Online (Sandbox Code Playgroud)

  • 在运行时进行较少的编译不会提高性能。有人尝试了很多方法,发现最有效的方法是使用 cssvars:https://github.com/ant-design/ant-design/issues/23371#issuecomment-634698379 (4认同)