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

Vue.js切换暗黑模式时过渡动画中断问题求助

为什么Vue中computed写法无法触发暗黑开关的CSS过渡动画?

我在App.vue中引入了自定义组件DarkSwitch.vue,该组件会为html元素添加.dark类,但切换暗黑模式时,开关的过渡动画会被中断。使用watch配合nextTick的临时方案可以解决此问题:

const isDarkClass = ref("");

watch(isDark, async () => {
  await nextTick();
  isDarkClass.value = isDark.value ? "translate-x-5" : "translate-x-0";
});

但使用computed的写法无法正常触发CSS过渡,代码如下:

<script setup>
import { useDark, useToggle } from "@vueuse/core";
import { computed } from "vue";

let isDark = useDark();
const toggleDark = useToggle(isDark);

const isDarkClass = computed(() => {
  return isDark.value ? "translate-x-5" : "translate-x-0";
});
</script>

<template>
  <button
    type="button"
    class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent bg-purple transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2 dark:bg-green"
    role="switch"
    @click="toggleDark()"
  >
    <span
      aria-hidden="true"
      class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
      :class="isDarkClass"
    ></span>
  </button>
</template>

原因分析

核心问题在于useDark()的状态更新和DOM上.dark类的添加是同步发生的,而computed会在isDark状态变化时立即更新开关的translate类名——这导致两个DOM样式变更(添加.dark类、修改开关位移类)在同一个Vue更新周期内完成。浏览器会把同周期内的DOM变更合并成一次重排/重绘,直接计算最终的DOM状态,跳过了从初始位移到目标位移的中间过程,自然无法触发CSS过渡动画。

而watch配合nextTick的方案,是把开关类名的更新推迟到下一个DOM更新周期:当isDark变化后,先等待Vue完成.dark类的DOM注入(nextTick会等待当前周期所有DOM操作执行完毕),再修改开关的位移类。这样浏览器会把这两个操作拆分成两次独立的重排/重绘,能清晰识别到位移样式的前后变化,从而正常触发过渡动画。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:07:11