如何在ExtJS 6.6 Classic Toolkit中实现主题切换器(明暗模式)
ExtJS 6.6 Classic Toolkit 主题切换实现方案
针对ExtJS 6.6 Classic的主题切换需求,以下是两种经过验证的可行方案,覆盖明暗模式切换和多主题切换场景:
方案一:动态替换主题CSS文件(支持多主题切换)
这种方法适合需要在多个完整主题(如Triton、Neptune、Triton暗色)之间切换的场景,核心是预编译所有主题的CSS文件,运行时动态替换页面中的CSS链接。
步骤1:预编译主题CSS
使用Sencha Cmd为每个需要切换的主题编译完整的CSS文件:
- 在项目根目录执行命令,编译指定主题:
sencha app build --theme triton sencha app build --theme triton-dark sencha app build --theme neptune - 编译完成后,将生成的
theme-[主题名]-all.css文件复制到项目的resources/css目录下统一管理。
步骤2:实现主题切换工具类
创建单例工具类处理CSS的加载与替换:
Ext.define('App.util.ThemeSwitcher', { singleton: true, currentTheme: 'triton', // 默认主题 switchTheme: function(themeName) { // 移除当前主题的CSS链接 const currentLink = Ext.dom.Query.select(`link[data-theme="${this.currentTheme}"]`)[0]; if (currentLink) { currentLink.parentNode.removeChild(currentLink); } // 加载新主题CSS(添加时间戳避免缓存) const themePath = `resources/css/theme-${themeName}-all.css?_dc=${new Date().getTime()}`; const newLink = document.createElement('link'); newLink.rel = 'stylesheet'; newLink.href = themePath; newLink.setAttribute('data-theme', themeName); document.head.appendChild(newLink); // 更新当前主题记录并持久化到本地存储 this.currentTheme = themeName; localStorage.setItem('app-selected-theme', themeName); // 刷新所有组件样式 Ext.ComponentQuery.query('*').forEach(comp => { if (comp.rendered) { comp.updateLayout(); typeof comp.refresh === 'function' && comp.refresh(); } }); }, // 页面加载时恢复用户上次选择的主题 init: function() { const savedTheme = localStorage.getItem('app-selected-theme') || this.currentTheme; this.switchTheme(savedTheme); } }); // 页面初始化时调用 Ext.onReady(() => { App.util.ThemeSwitcher.init(); });
步骤3:添加切换控件(下拉框/按钮)
以下拉框为例,实现主题选择界面:
Ext.create('Ext.form.ComboBox', { fieldLabel: '选择主题', store: Ext.create('Ext.data.Store', { fields: ['name', 'text'], data: [ { name: 'triton', text: 'Triton 亮色' }, { name: 'triton-dark', text: 'Triton 暗色' }, { name: 'neptune', text: 'Neptune' } ] }), valueField: 'name', displayField: 'text', value: App.util.ThemeSwitcher.currentTheme, listeners: { select: function(combo, record) { App.util.ThemeSwitcher.switchTheme(record.get('name')); } }, renderTo: Ext.getBody() });
方案二:CSS类切换(适合快速明暗模式切换)
如果仅需明暗模式切换,无需加载完整主题CSS,可以通过给body添加/移除类名的方式实现,编译主题时提前生成两种模式的样式规则。
步骤1:修改主题SASS变量
在当前主题的sass/var目录下(如triton/sass/var/Component.scss),通过body类名区分明暗模式变量:
// 默认亮色模式 $base-color: #f5f5f5; $text-color: #333; $border-color: #ddd; // 暗色模式 body.dark-mode { $base-color: #1a1a1a; $text-color: #ffffff; $border-color: #444; // 覆盖其他组件的变量,如网格表头、按钮样式等 $grid-header-background-color: darken($base-color, 10%); $button-base-color: darken($base-color, 15%); }
步骤2:编译主题并实现切换逻辑
编译主题后,通过简单的类名切换即可完成明暗模式切换:
function toggleDarkMode() { const body = document.body; const isDark = body.classList.toggle('dark-mode'); // 持久化设置 localStorage.setItem('app-dark-mode', isDark); // 刷新组件布局 Ext.ComponentQuery.query('*').forEach(comp => { comp.rendered && comp.updateLayout(); }); } // 页面初始化时恢复设置 Ext.onReady(() => { const isDark = localStorage.getItem('app-dark-mode') === 'true'; if (isDark) { document.body.classList.add('dark-mode'); } }); // 添加切换按钮 Ext.create('Ext.button.Button', { text: '切换明暗模式', handler: toggleDarkMode, renderTo: Ext.getBody() });
关键注意事项
- 主题编译必须用Sencha Cmd:ExtJS主题依赖大量SASS变量和混合宏,未编译的SASS文件无法直接在浏览器中使用。
- 组件样式刷新:部分复杂组件(如网格、树形控件)切换主题后需要手动调用
updateLayout()或refresh()更新样式。 - 缓存处理:动态加载CSS时添加
_dc参数,避免浏览器缓存旧的主题文件。
内容的提问来源于stack exchange,提问作者tamtejszystan
相关产品推荐
相关产品推荐

