問題#
每次刷新時,頁面閃屏,比如設定了黑色刷新初始為白色,然後又變為黑色
原因#
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',
},
],