英文:
Reacting to changes when switching from dark to light mode in Svelte
问题
我试图在主题从深色切换到浅色时显示特定消息。为了确定主题是浅色还是深色,我查看 document.documentElement.classList
并检查它是否包含 dark
,即类似 document.documentElement.classList.contains("dark")
的内容。
然而,当我尝试在脚本中以响应式方式绑定一个值时:
<script>
$: isDarkMode = document.documentElement.classList.contains("dark")
</script>
我收到了一个500内部错误。我不知道错误的来源是什么。
下面我提供了所有的代码,如果它在任何方面有帮助的话。
<script lang="ts">
function toggleTheme() {
if (document.documentElement.classList.contains("dark")) {
document.documentElement.classList.remove("dark");
} else {
document.documentElement.classList.add("dark");
}
}
$: isDarkMode = document.documentElement.classList.contains("dark");
</script>
<button on:click={toggleTheme}>切换主题</button>
{#if isDarkMode}
<p>欢迎来到黑暗面!</p>
{:else}
<p>请检查您的健康</p>
{/if}
注意:toggleTheme
按预期工作。起初,我认为问题与访问 document
有关,但似乎并非如此。
是否有人知道是什么导致了内部错误以及如何修复它?感谢您的帮助。
英文:
I am trying to display a certain message when theme changes from dark to light. To determine whether theme is light or dark, I look at document.documentElement.classList
and check if it contains dark
, i.e. something like document.documentElement.classList.contains("dark")
.
However, when I try to bind a value reactively in the script:
<script>
$: isDarkMode = document.documentElement.classList.contains("dark")
</script>
I receive a 500 internal error. I do not know what could be the source of the error.
Below I provide all the code, should it prove to be helpful in any way.
<script lang="ts">
function toggleTheme() {
if (document.documentElement.classList.contains("dark")) {
document.documentElement.classList.remove("dark");
} else {
document.documentElement.classList.add("dark");
}
}
$: isDarkMode = document.documentElement.classList.contains("dark");
</script>
<button on:click={toggleTheme}>Change theme</button>
{#if isDarkMode}
<p>Welcome to the dark side!</p>
{:else}
<p>Please have your health checked</p>
{/if}
Note: toggleTheme
works as expected. In the beginning, I assumed the problem had something to do with accessing the document
, but that does not seem to be the case.
Does someone know what is causing the internal error and how to fix it? Thank you for the help.
答案1
得分: 1
问题可能在于访问文档。在函数内部的使用并不重要,因为它只能在文档存在的浏览器中触发。如果存在服务器端渲染,任何在初始渲染期间发生的使用都会引发错误。
逻辑似乎相反,响应性将无法工作,因为 document
不是响应式的。可以使用本地标志,根据该标志设置类别。本地值将是响应式的,因为它在组件中声明。
您可以以不同的方式防范服务器端渲染问题,如果您使用 SvelteKit,可以使用 browser
标志。例如:
<script>
import { browser } from '$app/environment';
let isDarkMode = true;
$: if (browser) {
document.documentElement.classList.toggle('dark', isDarkMode);
}
</script>
<button on:click={() => isDarkMode = !isDarkMode}>Change theme</button>
如果不使用 SvelteKit,您可以在 onMount
中设置某些标志。
英文:
The problem probably is accessing the document. Usage within the function does not matter because that can only be triggered in the browser where the document exists. If there is server-side rendering, any usage that happens during initial rendering will cause errors.
The logic seems backward and the reactivity would not work, as document
is not reactive. Would instead use a local flag and set the class depending on that instead. The local value will be reactive as it is declared in the component.
You can guard against SSR issues in different ways, if you are using SvelteKit you can use the browser
flag. E.g.
<script>
import { browser } from '$app/environment';
let isDarkMode = true;
$: if (browser) {
document.documentElement.classList.toggle('dark', isDarkMode);
}
</script>
<button on:click={() => isDarkMode = !isDarkMode}>Change theme</button>
If not using SvelteKit, you could e.g. set some flag to true
in onMount
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论