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',
        },
      ],
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。