使用 VueUse 暗黑模式無法正常顯示轉場動畫特效
大约 3 分鐘
使用 VueUse 暗黑模式無法正常顯示轉場動畫特效
官方範例
以下是官方 useDark
的官方範例
import { useDark, useToggle } from "@vueuse/core";
const isDark = useDark();
const toggleDark = useToggle(isDark);
如果在 10.2.1
這個版本,會發現轉場動畫特效無法正常顯示,
然而在 9.13.0
這個版本,轉場動畫特效卻可以正常運作。
雖然 github 上有些人提出的解決方式是透過降板來處理,
但為了一探究竟我們將會把兩個版本的源碼做簡單的分析。
源碼查看
透過 VSCode 查看 useDark()
的定義
點開檔案 node_modules@vueuse\core\index.d.ts
index.d.ts
useDark
位於第 965 行
/**
* Reactive dark mode with auto data persistence.
*
* @see https://vueuse.org/useDark
* @param options
*/
declare function useDark(options?: UseDarkOptions): vue_demi.WritableComputedRef<boolean>;
UseDarkOptions
這裡可以看到 useDark 函式內可以傳入 UseDarkOptions
參數
進一步查看 UseDarkOptions
可以發現是繼承 UseColorModeOptions
位於第 938 行
interface UseDarkOptions extends Omit<UseColorModeOptions<BasicColorSchema>, 'modes' | 'onChanged'> {
/**
* Value applying to the target element when isDark=true
*
* @default 'dark'
*/
valueDark?: string;
/**
* Value applying to the target element when isDark=false
*
* @default ''
*/
valueLight?: string;
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridden.
*
* @default undefined
*/
onChanged?: (isDark: boolean) => void;
}
UseColorModeOptions
這邊就是關鍵!可以看到 9.13.0
和 10.2.1
的差異多了 disableTransition
這個選項
對應版本:9.13.0
interface UseColorModeOptions<T extends string = BasicColorSchema> extends UseStorageOptions<T | BasicColorSchema> {
/**
* CSS Selector for the target element applying to
*
* @default 'html'
*/
selector?: string;
/**
* HTML attribute applying the target element
*
* @default 'class'
*/
attribute?: string;
/**
* The initial color mode
*
* @default 'auto'
*/
initialValue?: T | BasicColorSchema;
/**
* Prefix when adding value to the attribute
*/
modes?: Partial<Record<T | BasicColorSchema, string>>;
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridden.
*
* @default undefined
*/
onChanged?: (mode: T | BasicColorSchema, defaultHandler: (mode: T | BasicColorSchema) => void) => void;
/**
* Custom storage ref
*
* When provided, `useStorage` will be skipped
*/
storageRef?: Ref<T | BasicColorSchema>;
/**
* Key to persist the data into localStorage/sessionStorage.
*
* Pass `null` to disable persistence
*
* @default 'vueuse-color-scheme'
*/
storageKey?: string | null;
/**
* Storage object, can be localStorage or sessionStorage
*
* @default localStorage
*/
storage?: StorageLike;
/**
* Emit `auto` mode from state
*
* When set to `true`, preferred mode won't be translated into `light` or `dark`.
* This is useful when the fact that `auto` mode was selected needs to be known.
*
* @default undefined
*/
emitAuto?: boolean;
}
對應版本:10.2.1
interface UseColorModeOptions<T extends string = BasicColorMode> extends UseStorageOptions<T | BasicColorMode> {
/**
* CSS Selector for the target element applying to
*
* @default 'html'
*/
selector?: string | MaybeElementRef;
/**
* HTML attribute applying the target element
*
* @default 'class'
*/
attribute?: string;
/**
* The initial color mode
*
* @default 'auto'
*/
initialValue?: MaybeRefOrGetter<T | BasicColorSchema>;
/**
* Prefix when adding value to the attribute
*/
modes?: Partial<Record<T | BasicColorSchema, string>>;
/**
* A custom handler for handle the updates.
* When specified, the default behavior will be overridden.
*
* @default undefined
*/
onChanged?: (mode: T | BasicColorMode, defaultHandler: (mode: T | BasicColorMode) => void) => void;
/**
* Custom storage ref
*
* When provided, `useStorage` will be skipped
*/
storageRef?: Ref<T | BasicColorSchema>;
/**
* Key to persist the data into localStorage/sessionStorage.
*
* Pass `null` to disable persistence
*
* @default 'vueuse-color-scheme'
*/
storageKey?: string | null;
/**
* Storage object, can be localStorage or sessionStorage
*
* @default localStorage
*/
storage?: StorageLike;
/**
* Emit `auto` mode from state
*
* When set to `true`, preferred mode won't be translated into `light` or `dark`.
* This is useful when the fact that `auto` mode was selected needs to be known.
*
* @default undefined
* @deprecated use `store.value` when `auto` mode needs to be known
* @see https://vueuse.org/core/useColorMode/#advanced-usage
*/
emitAuto?: boolean;
/**
* Disable transition on switch
*
* @see https://paco.me/writing/disable-theme-transitions
* @default true
*/
disableTransition?: boolean;
}
index.cjs
useColorMode
node_modules@vueuse\core\index.cjs
第 1667 行
function useColorMode(options = {}) {
const {
selector = "html",
attribute = "class",
initialValue = "auto",
window = defaultWindow,
storage,
storageKey = "vueuse-color-scheme",
listenToStorageChanges = true,
storageRef,
emitAuto,
disableTransition = true
} = options;
第 1698 行
if (disableTransition) {
style = window.document.createElement("style");
const styleString = "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";
style.appendChild(document.createTextNode(styleString));
window.document.head.appendChild(style);
}
這邊可以看到 disableTransition = true
以及符合條件就會強制清空轉場的效果
所以只要能將 disableTransition = false
傳入 useDark()
就可以了
結論
不想看長篇大論直接這樣抄
import { useDark, useToggle } from "@vueuse/core";
const isDark = useDark({ disableTransition: false });
const toggleDark = useToggle(isDark);
參考資料
使用【useDark, useToggle】控制 element-plus Switch 组件切换会导致动画异常
使用 useDark(), 发现 transition 动画失效?
Disable transitions on theme toggle