ReferenceError: document is not defined in Svelte 3

ReferenceError: document is not defined in Svelte 3

我正在尝试在 <script> 中手动 document.createElement 然后 appendChild 一个 audio 每次调用 eventListener 来替换它. 在浏览器中一切正常,除了页面加载时非常快的错误,但持续时间不到 100 毫秒。终端也有错误

ReferenceError: document is not defined
    at Object (webpack:///./src/components/Record/Component.svelte?:26:17)

上面好像是在文档还没有准备好的时候调用的,后来就好了,怎么解决?或者在 Svelte 世界 (Sapper) 中销毁和重新创建组件的首选方法是什么?

document 未在服务器上定义,因此您需要在组件中防止这种情况,以便特定的代码片段在浏览器中仅 运行。

您可以使用 onMount 函数,该函数仅在组件已呈现后在浏览器中 运行。

<script>
  import { onMount } from 'svelte';

  onMount(() => {
    document.createElement(...);

    // ...
  });
</script>

Sapper 适用于大多数您可能遇到的 third-party 库。然而,有时,third-party 库以允许它与多个不同模块加载器一起工作的方式捆绑在一起。有时,此代码会创建对 window 的依赖性,例如检查 window.global 是否存在。

由于在像 Sapper 的 server-side 环境中没有 window,简单地导入这样一个模块的操作可能会导致导入失败,并终止 Sapper 的服务器并出现错误,例如:

ReferenceError: window 未定义

解决此问题的方法是从 onMount 函数(仅在客户端调用)中为您的组件使用动态导入,这样就永远不会在服务器上调用您的导入代码。

<script>
    import { onMount } from 'svelte';

    let MyComponent;

    onMount(async () => {
        const module = await import('my-non-ssr-component');
        MyComponent = module.default;
    });
</script>

<svelte:component this={MyComponent} foo="bar"/>

感谢, I was also able to get my application working. Adding to Rutuja's answer, if anyone runs into this issue while using Sapper + Svelte + another package (in my case theme.js), you may also need to import multiple components. This is described in Mozilla's documentation here for import

When importing a default export with dynamic imports, it works a bit differently. You need to destructure and rename the "default" key from the returned object.

(async () => {
  if (somethingIsTrue) {
    const { default: myDefault, foo, bar } = await import('/modules/my-module.js');
  }
})();

对于我自己的项目(使用 theme.js),我必须使用以下逻辑(基于位于 heretheme.js 的 svelte 示例):

const themeState = {
    active: undefined,
    selected: undefined,
    themes: [],
}

onMount(async () => {
    const { default: Themer, auto, system } = await import('themer.js')

    themeState = {
        active: undefined,
        selected: light,
        themes: [light, dark, auto, system],
    }

    const themer = new Themer({
        debug: true,
        onUpdate: (theme) => (themeState.active = theme),
        themes: { light, dark, auto, system },
    })

    function noThemeSupport({ theme }) {
        return theme === 'system' && !themer.themeSupportCheck()
    }

    function setTheme(theme) {
        themeState.selected = theme
        themer.set(theme)
    }

    themer.set(themeState.selected)
})