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

在 Angular 中实现浅色/深色模式

在 Angular 中实现浅色/深色模式

浅色/深色模式切换是当今 Web 应用程序中非常常见的功能。对于最终用户来说,这个功能看起来可能很简单,但要在 Web 应用程序中正确实现它,却需要一些额外的工作。

本文将重点介绍使用 Angular 和现代 CSS 功能实现暗黑模式的最直接方法之一。

此外,作为额外福利,我还会分享一个包含一些相关附加功能的 Angular 项目示例。

让我们开始吧!

为什么在Angular中会遇到(一些)困难?

从宏观层面来说,实现暗黑模式需要一个 CSS-in-JS 库,以便可以使用 JavaScript 来操作 CSS。像 React 这样的 Web 库提供了极大的灵活性,可以集成任何 CSS-in-JS 库,从而帮助开发者轻松实现暗黑模式。

但Angular有所不同。作为一个框架,大部分功能都由框架本身处理,因此修改底层库的方式非常有限。此外,Angular默认的视图封装机制使得从外部修改组件样式变得非常困难。(显然,这正是其设计目的。)

高层架构

CSS 变量在其中扮演着重要角色。基本上,你可以根据 DOM 中的某个属性(通常是 CSS 元素class)来分配一些 CSS 变量body。然后,你可以使用 JavaScript 更改该属性,从而使 CSS 变量也随之改变,进而影响子组件的样式。

我将用图表来解释这一点。

Angular 中的浅色/深色模式是如何工作的

  1. 首先,根据 body 元素中的类定义并分配一组 CSS 变量。
  2. 这些 CSS 变量用于组件样式中
  3. 更新 body 元素中的类名以更改 CSS 变量赋值。最终也会影响组件样式。

让我们开始编写代码吧!

首先,让我们在全局styles.scss文件中定义一些样式变量。(本例中我使用的是 SCSS,但这完全是可选的。)



$bgColor_light: white;
$bgColor_dark: black;

$textColor_light: black;
$textColor_dark: white;

$borderColor_light: black;
$borderColor_dark: white;

// mixin that enables css variables in light mode
@mixin lighten() {
  --bgColor: #{$bgColor_light};
  --textColor: #{$textColor_light};
  --borderColor: #{$borderColor_light};
}

// mixin that enables css variables in dark mode
@mixin darken() {
  --bgColor: #{$bgColor_dark};
  --textColor: #{$textColor_dark};
  --borderColor: #{$borderColor_dark};
}


Enter fullscreen mode Exit fullscreen mode

现在我们需要以条件方式调用上述 mixin。我们使用 body 元素中的 CSS 类名来确定要调用哪个 mixin。



body.dark {
  @include darken();
}
body.light {
  @include lighten();
}


Enter fullscreen mode Exit fullscreen mode

现在你可以使用这些 CSS 变量来设置 Angular 组件的样式。



main {
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  background-color: var(--bgColor);
  color: var(--textColor);
}


Enter fullscreen mode Exit fullscreen mode

请确保不要在组件中直接使用 SCSS 变量,因为这些变量一旦定义就不会改变。

最后,让我们创建一个 Angular 组件,以编程方式更新元素中的 CSS 类document.body



  /**
   * Function that toggles the current mode
   * Exposed publicly
   */
  toggleMode() {
    this.document.body.classList.toggle(Mode.LIGHT);
    this.document.body.classList.toggle(Mode.DARK);
    if (this.currentMode === Mode.LIGHT) {
      this.updateCurrentMode(Mode.DARK);
    } else {
      this.updateCurrentMode(Mode.LIGHT);
    }
  }


Enter fullscreen mode Exit fullscreen mode

就这些。非常简单明了。

检查用户设备偏好设置

某些设备允许用户在系统设置中设置设备主题。因此,我们的 Web 应用程序必须能够兼容这些设备主题,并正确加载相应的模式。

您可以使用以下@media查询轻松验证这一点



@media (prefers-color-scheme: dark) {
    ...
}


Enter fullscreen mode Exit fullscreen mode

但是,我们将在您的 Javascript 逻辑中使用它。



/**

  • Init function that update the application based on the initial mode value
  • Flow as below
  • 1 - If there is a saved mode in the browser - use this as the initial value
  • 2 - If there is no saved mode, Check for the preferred device theme
  • 3 - If device theme is dark, set the init value to dark
  • 4 - Else set the default value to light */ private init() { const deviceMode = window.matchMedia("(prefers-color-scheme: dark)"); let initMode = this.modeStorage.get(); if (!initMode) { deviceMode.matches ? (initMode = Mode.DARK) : (initMode = Mode.LIGHT); } this.updateCurrentMode(initMode); this.document.body.classList.add(this.currentMode); }
Enter fullscreen mode Exit fullscreen mode




参考项目

正如我承诺的那样,我将分享我创建的示例项目,以演示上述实现以及一些其他功能,例如:

  • 浅色/深色模式切换按钮组件
  • 可用于实现自定义切换组件的 Angular 服务
  • 通过本地存储实现持久化(也能够编写其他持久化方法,例如会话存储)
  • 基于 RxJS Observable 的模式切换监听器
  • SCSS 支持 CSS 变量
  • 根据设备主题偏好加载初始模式
  • 无需其他库
  • 文档齐全的代码

Angular 浅色/深色模式实现

Github:Angular Light / Dark App

您可以在文件中找到所有开发信息README.md

今天就到这里。欢迎分享您的反馈意见。感谢阅读。

文章来源:https://dev.to/pahanperera/implement-light-dark-mode-in-angular-42ff