首页 > 解决方案 > 如何在 Svelte 中使用开关渲染组件?

问题描述

我想使用switch caseSvelte 中的语句有条件地渲染组件,如下所示:

// index.svelte

<script>
import TextContent from './components/text-content.svelte'
import { someData } from './api/some-data.js'


    const ContentSwitch = (data) => {
        switch (data._type) {
            case 'block':
                return data.children.map((child) => ContentSwitch(child));
            case 'span':
                return (
                    <TextContent>
                        <span slot="text-content">{data.text}</span>
                    </TextContent>
                );
        }
        for (let index = 0; index < data.length; index++) {
            return data.map((item) => ContentSwitch(item));
        }
    };

</script>

<div>
    {#each someData as data}
        {ContentSwitch(data)}
    {/each}
</div>

文本内容组件:

// components/text-content.svelte

<slot name="text-content">
    <span />
</slot>

似乎这种方法在 Svelte 中不起作用,因为我遇到了Unexpected Token错误。

在 Svelte 中是否可以使用开关渲染组件?

标签: javascriptswitch-statementsveltesveltekit

解决方案


你在那里写的更像是用于 React 的 JSX。在 Svelte 中,您不会在 JavaScript 中编写 HTML,而是将它们分开。

您要做的是制作一个查找表并使用 svelte:component 来呈现正确的组件:

<script>
  const BlockTypes = {
    "span": TextContent
  }
</script>

{#each children as child}
  {#if child.type === 'block'}
    <svelte:self {...child} />
  {:else}
    <svelte:component this={BlockTypes[child.type]} {...child} />
  {/if}
{/each}

svelte:self假设它本身也是块类型的元素,因为你不能将组件导入到自身中,所以你需要这个特殊情况。有了这个,你就可以开箱即用地嵌套块。

在此示例中,您将子组件的所有属性传递给渲染组件,因此您必须稍微重写您的组件,您也可以使用插槽,但这对于命名插槽会造成严重的混乱。


推荐阅读