SkinManager类实现多主题皮肤管理,通过结构化主题配置、事件解耦、localStorage持久化及自动还原机制,支持动态注册、CSS变量注入与系统偏好适配,确保可扩展与易维护。

在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
<p>用 JavaScript 面向对象方式实现多主题皮肤管理器,核心是把“主题”抽象为对象,把“切换行为”封装进类,避免全局变量和硬编码样式,做到可扩展、易维护。</p>
<H3>定义 SkinManager 类,统一管理主题生命周期</H3>
<p>创建一个 SkinManager 类,负责加载、激活、存储和监听主题。它不直接操作 DOM 样式,而是通过约定好的 CSS 自定义属性(CSS Variables)或 class 名来驱动视图变化。</p>
<ul>
<li>构造时读取当前主题(从 localStorage 或默认值),初始化状态</li>
<li>提供 <strong>setTheme(themeKey)</strong> 方法:卸载旧主题 class、添加新主题 class、更新 localStorage、触发 change 事件</li>
<li>支持 <strong>addTheme(key, config)</strong> 动态注册新主题(比如深色、高对比、护眼绿)</li>
<li>内部维护 themes Map,key 是主题标识(如 'light'/'dark'/'blue'),value 是含 name、cssClass、vars 等信息的配置对象</li>
</ul>
<H3>主题配置结构化,分离样式与逻辑</H3>
<p>每个主题不是一堆 CSS 字符串,而是结构化对象,便于复用和运行时注入:</p>
<ul>
<li><strong>cssClass</strong>:要加到 document.body 上的 class 名(如 'theme-dark'),对应预设的 CSS 规则</li>
<li><strong>vars</strong>:可选的 CSS 自定义属性映射(如 <font color="#2a5fec">{'--primary': '#3b82f6', '--bg': '#1e293b'}</font>),可在切换时批量设置到 :root</li>
<li><strong>onLoad</strong>:可选回调,用于加载外部 CSS 文件(如动态 import('./themes/dark.css'))</li>
</ul>
<p>这样新增主题只需调用 <strong>skinManager.addTheme('sepia', { cssClass: 'theme-sepia', vars: { '--bg': '#f4f0e5', '--text': '#5a4a42' } })</strong>,无需改主逻辑。</p>
<H3>用事件机制解耦,让 UI 自行响应主题变化</H3>
<p>不要在 SkinManager 里写按钮点击逻辑或 DOM 操作。它只负责“通知”:</p>
<ul>
<li>内置 <strong>EventTarget</strong> 实例(或用自定义事件),暴露 <strong>onchange</strong> 属性或 <strong>addEventListener('change', handler)</strong></li>
<li>当 setTheme 执行完成,派发 { theme: 'dark', prevTheme: 'light' } 事件</li>
<li>页面中任意模块(如 Header、SettingsPanel)可独立监听,决定是否重绘、保存用户偏好、更新图标等</li>
</ul>
<p>例如:<font color="#2a5fec">document.getElementById('theme-toggle').addEventListener('click', () => skinManager.setTheme('dark'))</font>,完全解耦。</p>
<H3>持久化与初始化自动还原</H3>
<p>用户刷新页面后应恢复上次选择的主题:</p>
<ul>
<li>构造 SkinManager 时,先从 localStorage 读取 savedThemeKey</li>
<li>若存在且已注册,则立即调用 setTheme(savedThemeKey),否则 fallback 到默认主题</li>
<li>每次成功 setTheme 后,自动写入 localStorage.setItem('preferred-theme', key)</li>
<li>可搭配媒体查询检测系统偏好(<font color="#2a5fec">window.matchMedia('(prefers-color-scheme: dark)')</font>),作为初始 fallback</li>
</ul>
<p>这样既尊重用户选择,又兼容系统设置,无需额外判断逻辑散落在各处。</p>

















