发布于 2026-01-06 10 阅读
0

如何使用 React Hooks 实现深色模式

如何使用 React Hooks 实现深色模式

深色模式是目前应用和网站广泛采用的最新功能之一。深色可以延长移动设备的电池续航时间。据谷歌称,YouTube 应用的深色模式在 50% 亮度下可节省 15% 的电量,在 100% 亮度下则可节省高达 60% 的电量。苹果公司已确认,从 2020 年起,其手机将全部采用 OLED 屏幕。

点击此处查看完整演示。此演示的完整代码可在此处找到。

为什么选择 React Hooks?

我们知道 React 组件支持自上而下的数据流,这有助于我们将应用程序组织成易于管理的小 UI 单元。然而,如果仅使用组件模型,组件会变得庞大且难以重构。此外,组件之间可能存在逻辑重复的情况。Hooks 的优势在于,它允许我们将组件内的逻辑组织成易于复用的独立单元。

然而,我们常常无法进一步分解复杂的组件,因为其逻辑是有状态的,无法提取到函数或其他组件中。——丹·阿布拉莫夫

实现钩子

为了简化演示如何在React Hooks中实现深色模式,我们将使用localStorage,以便浏览器在页面重新加载时记住用户的偏好设置。在更复杂的 Web 应用中,用户的偏好设置可以存储在数据库中。那么,让我们从 Facebook 的标准 React 样板代码开始。克隆仓库,切换到新创建的项目文件夹,然后运行应用程序。更多信息,请参阅文档

npx create-react-app dark-mode;
cd dark-mode;
npm start;
Enter fullscreen mode Exit fullscreen mode

接下来,我们来添加 CSS 颜色变量。我们可以先从一种颜色和一个背景色开始,但如果您想构建一个更大的配色方案,可以添加更多变量。这样,我们就以一种一致的方式模块化了颜色样式,可以轻松地在整个网站中实现。

// App.css

...

html[data-theme="light"]  {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}

html[data-theme="dark"]  {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

...

Enter fullscreen mode Exit fullscreen mode

要设置变量,请按如下方式替换App.css文件中的header CSS :

// App.css

...

.App-header {
  background-color:var(--background-color);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color:var(--color);
}

...

Enter fullscreen mode Exit fullscreen mode

创建主题切换组件

在 src* 文件夹中创建一个新文件,并将其命名为 **ThemeToggle**或类似名称。目前这是一个入门项目,如果您愿意,可以创建一个单独的ThemeToggle目录。在这里,我们将使用useState hook 来存储当前主题偏好设置。

// ThemeToggle.js

...

  const ThemeToggle = () => {
    const [darkMode, setDarkMode] = useState(
      localStorage.getItem("theme") === "dark" ? true : false
    );
    useEffect(() => {
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
    }, []);
  };

...

Enter fullscreen mode Exit fullscreen mode

如果用户是首次访问该网站,localStorage中不会设置任何偏好设置。我们的严格相等性比较运算符将返回false,并调用darkMode钩子将浅色主题应用于整个应用程序。

这是通过 HTML 的data- 属性实现的,它允许我们将信息存储在语义化的 HTML 元素中。我们将在用于切换主题(深色或浅色)的方法中使用它。使用相同的逻辑,我们也可以调用之前设置的setDarkMode钩子函数,将主题信息存储在localStorage中。

// ThemeToggle.js

...

  const switchThemes = () => {
    if (isDark === false) {
      localStorage.setItem("theme", "dark");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
      setDarkMode(true);
    } else {
      localStorage.setItem("theme", "light");
      document
        .getElementsByTagName("HTML")[0]
        .setAttribute("data-theme", localStorage.getItem("theme"));
      setDarkMode(false);
    }
  };

...

Enter fullscreen mode Exit fullscreen mode

在ThemeToggle中,我们需要做的最后一件事是返回要导入的按钮。

// ThemeToggle.js

...

  return (
    <label className="switch">
      <input
        type="checkbox"
        defaultChecked={isDark}
        onChange={() => toggleThemeChange()}
      />
      <span className="slider round" />
    </label>
  );

...

Enter fullscreen mode Exit fullscreen mode

现在,为了进行测试,我们可以将其导入到我们的App.js中。

// App.js

...

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          React Hooks Dark Mode Starter
        </p>
        <ThemeToggle />
      </header>
    </div>
  );
}

...

Enter fullscreen mode Exit fullscreen mode

恭喜!!

现在,您有了一个可用的元素,可以将其放置在应用程序中的任何位置。如果您想查看完整代码或创建自己的分支,请访问我的代码仓库(链接在此)

原文发布于https://www.josephc.how/react-hooks-dark-mode/

文章来源:https://dev.to/chowjiaming/how-to-do-dark-mode-with-react-hooks-23gi