如何在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>

TextContent组件:

// components/text-content.svelte
<slot name="text-content">
<span />
</slot>

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

是渲染组件与开关可能在Svelte?

你写的东西更像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假定它本身也是block类型的元素,由于原因你不能将组件导入到它自己,所以你需要这里的这个特殊情况。有了这个,你就可以开箱使用嵌套块了。

在这个例子中,你将子组件的所有属性传递给渲染组件,所以你必须稍微重写你的组件,你也可以使用插槽,但这将是一个严重的混乱与命名插槽。

我认为在(java)脚本标记内的开关'span'中返回html语法不能这样工作。
实际上它不是在不同组件之间切换,而是呈现不同嵌套的数据。文本字段都在一个TextContent组件?

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

相关内容

  • 没有找到相关文章

最新更新