繁体   English   中英

如何在 Svelte 中使用开关渲染组件?

[英]How do I render components with a switch in Svelte?

我想在 Svelte 中使用switch case语句有条件地呈现组件,如下所示:

// 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 中可以使用开关渲染组件吗?

我认为在 (java)script 标签内的 switch 'span' 中返回 html 语法不能像这样工作。
实际上,这不是不同组件之间的切换,而是在 TextContent 组件内呈现不同的嵌套“data.text”字段?

someData的结构是什么? 假设它看起来像这样

let someData = [
{
  _type: 'block',
  children: [{
  _type: 'span',
  text: 'textValue#1'
  }]
},
{
  _type: 'span',
  text: 'textValue#2'
}
]

递归函数可用于获取所有嵌套的文本字段

    function getSpanTexts(dataArr) {
        return dataArr.flatMap(data => {
            switch (data._type) {
            case 'block':
                return getSpanTexts(data.children)
            case 'span':
                return data.text                
        }
        })
    }
    
    $: textArr = getSpanTexts(someData)  // ['textValue#1', 'textValue#2']

然后可以使用 html 中的 each 循环来迭代文本字段,每个循环都在 TextContent 组件中呈现

<div>
    {#each textArr as text}
         <TextContent>
             <span slot="text-content">{text}</span>
         </TextContent>
    {/each}
</div>

查看代码片段的这个工作 REPL

你在那里写的东西更像是用于 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是假设,这本身也是块类型的元素,其原因不能导入一个组件插入到自己,所以你在这里需要这种特殊情况下。 有了这个,你就可以开箱即用地嵌套块。

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

暂无
暂无

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

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