Me gustaría representar componentes condicionalmente con una declaración de switch case en Svelte así:
// 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>Componente de contenido de texto:
// components/text-content.svelte <slot name="text-content"> <span /> </slot> Parece que este enfoque no funciona en Svelte ya que recibo un error de Unexpected Token .
¿Es posible renderizar componentes con un interruptor en Svelte?
Lo que estás escribiendo allí se parece más a JSX, que es para React. En Svelte, no escribe HTML en su JavaScript, sino que los mantiene separados.
Lo que haría es crear una tabla de búsqueda y usar svelte:component para representar el componente correcto:
<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} El svelte:self está bajo el supuesto de que esto es en sí mismo también un elemento de tipo bloque, por razones que no puede importar un componente en sí mismo, por lo que necesita este caso especial aquí. Tener esto le da bloques anidados fuera de la caja.
En este ejemplo, pasa todas las propiedades del elemento secundario al componente renderizado, por lo que tendría que reescribir ligeramente sus componentes, también podría usar ranuras, pero eso sería un gran problema con las ranuras con nombre.
Creo que devolver la sintaxis html en el interruptor 'span' dentro de la etiqueta de script (java) no puede funcionar así.
En realidad, no se trata de un cambio entre diferentes componentes, sino de representar campos 'data.text' anidados de manera diferente, todos dentro de un componente TextContent.
¿Cuál es la estructura de someData? Suponiendo que se parece a esto
let someData = [ { _type: 'block', children: [{ _type: 'span', text: 'textValue#1' }] }, { _type: 'span', text: 'textValue#2' } ]Se podría usar una función recursiva para obtener todos los campos de texto anidados
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']Luego, los campos de texto se pueden iterar con cada bucle dentro del html, cada uno representado dentro de un componente TextContent
<div> {#each textArr as text} <TextContent> <span slot="text-content">{text}</span> </TextContent> {/each} </div>Vea este REPL de trabajo de los fragmentos de código