如何在Angular SSR中实现暗黑模式(darkMode)?
Angular SSR 暗黑模式实现方案
以下是几种在Angular SSR中实现暗黑模式的可靠方法:
1. 安全访问浏览器API,避免服务端报错
通过Angular提供的PLATFORM_ID区分服务端与客户端环境,仅在浏览器中调用window.matchMedia相关逻辑:
import { Component, OnInit, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-theme-toggle', templateUrl: './theme-toggle.component.html' }) export class ThemeToggleComponent implements OnInit { isDarkMode = false; constructor(@Inject(PLATFORM_ID) private platformId: Object) {} ngOnInit(): void { if (isPlatformBrowser(this.platformId)) { // 读取系统主题偏好 const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)'); this.isDarkMode = darkModeQuery.matches; // 监听系统偏好变化 darkModeQuery.addEventListener('change', (e) => { this.isDarkMode = e.matches; this.updateThemeClass(); }); // 读取用户手动保存的主题选择(若有) const savedTheme = localStorage.getItem('theme'); if (savedTheme) { this.isDarkMode = savedTheme === 'dark'; } this.updateThemeClass(); } } toggleTheme(): void { this.isDarkMode = !this.isDarkMode; this.updateThemeClass(); localStorage.setItem('theme', this.isDarkMode ? 'dark' : 'light'); } private updateThemeClass(): void { document.body.classList.toggle('dark', this.isDarkMode); } }
2. 服务端预渲染匹配用户偏好(可选)
若希望服务端直接渲染符合用户偏好的主题,可通过读取请求Cookie实现:
在server.ts中处理请求时,读取用户存储的主题Cookie,修改渲染的HTML内容:
// server.ts 相关处理逻辑 server.get('*', (req, res) => { const theme = req.cookies.theme || 'light'; const indexHtml = fs.readFileSync(join(distFolder, 'index.html'), 'utf-8'); // 给body标签添加主题类 const modifiedHtml = indexHtml.replace( '<body>', `<body class="${theme === 'dark' ? 'dark' : ''}">` ); res.render(modifiedHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); });
3. 全局CSS变量配合主题类
在全局样式文件(如styles.css)中定义主题变量,通过切换dark类实现主题切换:
:root { --bg-color: #ffffff; --text-color: #121212; } .dark { --bg-color: #121212; --text-color: #ffffff; } body { background-color: var(--bg-color); color: var(--text-color); transition: background-color 0.3s, color 0.3s; }
所有使用这些变量的组件会自动跟随主题变化。
内容的提问来源于stack exchange,提问作者Raphaël Balet
相关产品推荐
相关产品推荐

