简体   繁体   English

我可以在延迟加载的 Svelte 组件中访问上下文吗?

[英]Can I access context in lazily loaded Svelte component?

I have this simple Svelte component:我有这个简单的 Svelte 组件:

<script lang="ts">
    import { getContext } from "svelte";
    let value = getContext('test');
</script>

<div>
    <p>{value}</p>
</div>

It is lazily loaded inside another component like this (note, this component is compiled completely separately from the lazy component):它像这样延迟加载到另一个组件中(请注意,该组件与延迟组件完全分开编译):

<script lang="ts">
    import { onMount, setContext } from "svelte";
    let lazyRow = null;
    onMount(async () => {
      try {
        lazyRow = import("http://localhost/wc/row.js");
      } catch (e) {
        console.error(e);
      }
  })
  setContext('test', 'This is my context value');
</script>

{#if lazyRow}
    {#await lazyRow then { default: Row }}
        <Row />
    {/await}
{:else}
<p>Loading</p>
{/if}

Unfortunately when the component gets loaded and rendered it bombs out with the following error:不幸的是,当组件被加载并渲染时,它会出现以下错误:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '$$')未捕获(承诺)TypeError:无法读取未定义的属性(读取“$$”)

I would have expected my Row component simply to render the text 'This is my context value', but I get the aforementioned error instead.我原以为我的行组件只是呈现文本“这是我的上下文值”,但我却得到了上述错误。

I've been googling around for this for a few hours but haven't been able to figure it out.我已经为此搜索了几个小时,但一直无法弄清楚。 Is it simply not possible to use contexts in lazily loaded components?是否根本不可能在延迟加载的组件中使用上下文?

Update更新

So I figured out the problem with help from the comments below.所以我在下面的评论的帮助下解决了这个问题。 The problem is that when the app and components are compiled separately they both include their own version of the svelte internals, so that includes things like current_component , etc. I will have to tweak my build logic in order for the app and components to share the same svelte internals.问题是,当应用程序和组件分别编译时,它们都包含它们自己的 svelte 内部版本,因此包括current_component等内容。我将不得不调整我的构建逻辑,以便应用程序和组件共享同样苗条的内部结构。 I'm not sure yet how, but I'll figure it out.我还不确定如何,但我会想办法的。

Update 2更新 2

While it is technically possible to share Svelte internals between an app and an externally loaded lazy component, in the end that isn't going to scale.虽然技术上可以在应用程序和外部加载的惰性组件之间共享 Svelte 内部结构,但最终无法扩展。 So, I have come to the conclusion that this particular route isn't viable for the time being.所以,我得出的结论是,这条特定路线暂时不可行。

The component would just render undefined if the context were not to be found.如果找不到上下文,该组件只会呈现undefined

The problem has to be the import/file itself;问题必须是导入/文件本身; it probably does not export a valid/fully compiled component as default .它可能不会将有效/完全编译的组件导出为default组件。

You usually also would not import from localhost via an absolute URL which just breaks when deployed.您通常也不会通过绝对 URL 从 localhost 导入,它在部署时会中断。 I would rather expect something like import('./Row.svelte') and the build system should take care of the rest (compiling, code splitting, bundling, etc.).我宁愿期待像import('./Row.svelte')这样的东西,构建系统应该处理 rest(编译、代码拆分、捆绑等)。


While this should work if the component is valid, there is a scenario in which the context would be missing: When the component is constructed via the client-side API.虽然这在组件有效的情况下应该有效,但存在上下文缺失的情况:当通过客户端 API 构建组件时。

In this case, the context has to be manually forwarded, eg like this:在这种情况下,必须手动转发上下文,例如:

import { onMount, setContext, getAllContexts } from "svelte";

setContext("test", "This is my context value");
const context = getAllContexts();

onMount(async () => {
    try {
        const Row = await import("./row.svelte").then(m => m.default);
        new Row({ target: document.body, context });
    } catch (e) {
        console.error(e);
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM