Astro/Svelte组件无法访问document元素的问题及解决方法
解决Astro/Svelte主题切换组件中的“document is not defined”错误
我编写了一个实现主题切换的Astro/Svelte组件,点击按钮时能正常打印document.documentElement.classList,但在响应式代码块中操作document时,出现了**"document is not defined"**的错误。
原组件代码如下:
<script lang="ts"> let theme = localStorage.getItem("theme") ?? "light"; const handleClick = () => { theme = (theme === "light" ? "dark" : "light"); console.log('classlist',document.documentElement.classList); }; $:{ if (theme === "dark") { document!.documentElement.classList.add("dark"); } else { document!.documentElement.classList.remove("dark"); } localStorage.setItem("theme", theme); } </script> <button on:click={handleClick}>{theme === "light" ? "🌙" : "🌞"}</button>
感谢@H.B提供的解决方案,通过引入Svelte的onMount钩子,确保仅在组件挂载到客户端DOM后再执行操作document的代码,避免了服务端渲染时找不到document的问题。修改后的代码如下:
<script lang="ts"> import { onMount } from "svelte"; let theme = localStorage.getItem("theme") ?? "light"; let flag = false; onMount(()=>{ flag = true }) $: if (flag) { if ( theme === 'dark') { document!.documentElement.classList.add("dark"); } else { document!.documentElement.classList.remove("dark"); } localStorage.setItem("theme", theme); } const handleClick = () => { theme = (theme === "light" ? "dark" : "light"); console.log('classlist',document.documentElement.classList); }; </script> <button on:click={handleClick}>{theme === "light" ? "🌙" : "🌞"}</button>
修改后的代码可正常运行,核心思路是利用onMount仅在客户端触发的特性,通过flag变量控制响应式代码块的执行时机,确保操作document时环境已存在该对象。
内容的提问来源于stack exchange,提问作者Juan Martín Jaimes Mendoza
相关产品推荐
相关产品推荐

