我尝试在<script>
中手动document.createElement
,然后在每次调用appendChild
来替换audio
时eventListener
。 所有功能在浏览器中都能正常运行,除了页面加载时确实非常快速的错误,但持续时间不到100ms 。终端机中也有错误
ReferenceError: document is not defined
at Object (webpack:///./src/components/Record/Component.svelte?:26:17)
似乎在文档还没有准备好但后来没问题的时候调用了上面的方法,该如何解决?还是在Svelte world(Sapper)中销毁和重新创建组件的首选方法是什么?
答案 0 :(得分:7)
Sapper与您可能会遇到的大多数第三方库很好地配合使用。但是,有时第三方库以某种方式捆绑在一起,使其可以与多个不同的模块加载器一起使用。有时,这段代码会创建对window的依赖关系,例如检查window.global是否存在。
由于在服务器端环境(如Sapper的环境)中没有窗口,因此简单地导入此类模块的操作可能导致导入失败,并以诸如以下错误终止Sapper的服务器:
ReferenceError:未定义窗口
解决此问题的方法是从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"/>
答案 1 :(得分:2)
document
未在服务器上定义,因此您需要在组件中加以防范,以便特定的代码段仅在浏览器中运行。
您可以使用onMount
函数,该函数仅在呈现组件后才在浏览器中运行。
<script>
import { onMount } from 'svelte';
onMount(() => {
document.createElement(...);
// ...
});
</script>
答案 2 :(得分:1)
感谢Rutuja's answer here,我也能够使我的应用程序正常运行。添加到Rutuja的答案中,如果有人在使用Sapper + Svelte +其他软件包(在我的情况下为theme.js
)中遇到此问题,则可能还需要导入多个组件。这在Mozilla's documentation here for import中有描述。
使用动态导入导入默认导出时,它的工作原理 不一样。您需要对以下文件进行解构并重命名“默认”键: 返回的对象。
(async () => { if (somethingIsTrue) { const { default: myDefault, foo, bar } = await import('/modules/my-module.js'); } })();
对于我自己的项目(使用theme.js
),我必须使用以下逻辑(基于位于here的theme.js
的精巧示例):
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)
})