如何解决四季主题切换时body类名叠加、事件监听器堆叠的问题
问题根源
- 原代码每个季节的点击事件仅对当前主题类执行
toggle操作,没有清除其他季节的主题类,导致类名叠加 - 多份独立的sessionStorage存储逻辑冗余,也容易出现状态不一致的问题
修复方案
轻量改法(无需重构现有代码)
如果不想改动原有代码结构,只需要在每个季节的点击事件最开头,先移除另外三个季节的主题类,把toggle改成add即可,以春季逻辑为例修改后:
//spring change springIcon.addEventListener('click', () => { // 新增:先移除其他三个季节的主题类 document.body.classList.remove('summer-theme', 'autumn-theme', 'winter-theme'); // 把toggle改为add,直接启用春季主题不需要判断原有状态 document.body.classList.add('spring-theme'); spring.classList.add('show-icon'); summer.classList.remove('show-icon'); autumn.classList.remove('show-icon'); winter.classList.remove('show-icon'); // 存储逻辑可以简化为直接存true,其他季节的存储值点击对应图标时再改即可 sessionStorage.setItem("spring-theme", "true") sessionStorage.setItem("summer-theme", "false") sessionStorage.setItem("autumn-theme", "false") sessionStorage.setItem("winter-theme", "false") })
其余三个季节的逻辑按照相同规则修改即可,不会影响body上原有的固定类名(比如你示例里的b-page)。
优化改法(抽离公共逻辑减少冗余)
如果希望减少重复代码,后期维护更方便,可以把四季的公共逻辑统一管理:
// 统一配置所有主题信息 const themes = [ { name: 'spring', icon: springIcon }, { name: 'summer', icon: summerIcon }, { name: 'autumn', icon: autumnIcon }, { name: 'winter', icon: winterIcon } ] const themeClassList = themes.map(t => `${t.name}-theme`) // 页面初始化时读取存储的主题加载对应样式 const activeTheme = sessionStorage.getItem('activeTheme') if (activeTheme) { document.body.classList.remove(...themeClassList) document.body.classList.add(`${activeTheme}-theme`) themes.forEach(t => { t.icon.classList.toggle('show-icon', t.name === activeTheme) t.icon.classList.toggle('hide-icon', t.name !== activeTheme) }) } // 统一绑定点击事件 themes.forEach(theme => { theme.icon.addEventListener('click', () => { // 清除所有主题类后添加当前选中的主题 document.body.classList.remove(...themeClassList) document.body.classList.add(`${theme.name}-theme`) // 统一处理图标显隐 themes.forEach(t => { t.icon.classList.toggle('show-icon', t.name === theme.name) t.icon.classList.toggle('hide-icon', t.name !== theme.name) }) // 仅用一个字段存储当前选中的主题,无需维护4个存储变量 sessionStorage.setItem('activeTheme', theme.name) }) })
内容的提问来源于stack exchange,提问作者Rach
相关产品推荐
相关产品推荐

