You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生JS实现类似Vue的class绑定,完成深色模式切换动画

核心问题梳理

你现有代码的问题主要集中在以下几点:

  • 给开关添加pull动画类后立即清空,导致0.5s的动画完全无法触发
  • 没有对应Vue示例中的animationend事件监听,无法在动画结束后正确重置状态,会导致下次点击无法重新触发动画
  • 直接操作className会覆盖元素原有其他样式类,且主题初始化逻辑存在冗余
  • 主题切换时机和动画进度没有匹配,交互体验不连贯

修正后完整代码

HTML 部分(确保元素id匹配)

<div id="switch" class="switch"></div>

你现有的CSS代码不需要改动,如果需要主题切换时的颜色过渡效果,可以额外添加以下样式:

body {
  transition: background-color 0.3s, color 0.3s ease;
}

JS 部分

const switchEl = document.getElementById('switch');

// 页面加载时初始化本地存储的主题
if (localStorage.getItem('css')) {
  document.body.classList.add('dark');
}

// 监听动画结束事件,自动重置动画类,保证下次点击可重新触发动画
switchEl.addEventListener('animationend', () => {
  switchEl.classList.remove('pull');
});

// 点击切换逻辑
switchEl.addEventListener('click', () => {
  // 先触发拉绳下落动画
  switchEl.classList.add('pull');
  // 动画执行到中间节点(拉绳落到最低点)时切换主题,匹配交互逻辑
  setTimeout(() => {
    const isDark = document.body.classList.contains('dark');
    if (isDark) {
      document.body.classList.remove('dark');
      localStorage.removeItem('css');
    } else {
      document.body.classList.add('dark');
      localStorage.setItem('css', 'dark');
    }
  }, 250);
});

补充说明

如果希望拉绳动画完全结束后再切换主题,将setTimeout的延时参数从250改为500即可。

内容的提问来源于stack exchange,提问作者漫磋嗟

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:45:05