ryne

ryne

github

nuxt + useDark 暗黑模式閃屏問題

問題#

每次刷新時,頁面閃屏,比如設定了黑色刷新初始為白色,然後又變為黑色

原因#

useDark 預設儲存在 local storage 中,而 ssr 狀態下獲取不到 local storage

處理#

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          innerHTML: `
            (function() {
              const isDark = localStorage.getItem('darkMode') === 'true' || 
                (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches);
              document.documentElement.classList.toggle('dark', isDark);
            })();
          `,
          type: 'text/javascript',
        },
      ],
    },
  },
})

後續問題#

Hydration class mismatch

原因#

雖然解決了閃屏問題,但是 useDark 在 ssr 時初始化的值還是一個錯誤的值(獲取不到 local storage)

解決#

使用 seesion 來儲存

const isDark = useDark({
    storageKey: 'vueuse-color-scheme',
    storage: {
      getItem(key: string) {
        if (import.meta.server) {
          // 服務端從 headers 中獲取 cookie
          const cookieStr = useRequestHeaders(['cookie'])?.cookie || ''
          return cookieStr.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
        }
        return document.cookie.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
      },
      setItem(key: string, value: string) {
        document.cookie = `${key}=${value};path=/;max-age=${60 * 60 * 24 * 30}`
      },
    } as Storage,
  })
// nuxt.config.ts
script: [
        {
          innerHTML: `
            (function() {
              var getCookie = function(name) {
                return document.cookie.split('; ').find(row => row.startsWith(name))?.split('=')[1] || null;
              };
              var darkMode = getCookie('vueuse-color-scheme');
              if (darkMode === 'dark') {
                document.documentElement.classList.add('dark');
              } else {
                document.documentElement.classList.remove('dark');
              }
            })();
          `,
          type: 'text/javascript',
        },
      ],
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。