Como estoy cambiando un proyecto de React a SvelteKit, tengo una situación específica que me hizo sentir mucha curiosidad al respecto.
Supongamos que tengo un componente en React que recibe el objeto columnsMockExample como accesorios, por ejemplo, y consume un HTML dentro del objeto, como:
const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }] <ColumnsComponent columnsProp={columnsMockExample}/> Entonces, en React, podríamos mapear este objeto para consumirlo y mostrar cada .html dentro de columnsMockExample :
{props.columnsProp.map((columnFromMockExample) => columnFromMockExample.html)};
Entonces, aquí está la pregunta: como SvelteKit tiene la etiqueta <script/> aparte del HTML, ¿cómo puedo crear mi objeto columnsMockExample dentro de la etiqueta SvelteKit <script/> ya que no es JSX?
El ejemplo de script SvelteKit incorrecto se escribe a continuación:
<script> const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }] </script>Gracias.
Si es HTML puro (sin código específico de Svelte, solo HTML sin procesar), puede usar la directiva @html :
<script> const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }] </script> {#each columnsMockExample as example} {@html example.html} {/each}Documentos: https://svelte.dev/docs#template-syntax-html
Sin embargo, si hay componentes Svelte o controladores de clic, etc., eso no funciona. En ese caso, debe reescribir el código utilizando componentes y ranuras ( https://svelte.dev/docs#template-syntax-slot ) y/o la etiqueta svelte:component ( https://svelte.dev/docs#template -syntax-svelte-component ) - cómo depende exactamente de cuál sea su objetivo.
Hay varios enfoques diferentes que se pueden tomar aquí, todos los cuales son un poco diferentes.
Use ranuras para hacer que cada columna represente una celda y filas completas a través de la ranura de los componentes principales. El ejemplo se puede ver en esta pregunta .
Defina componentes separados y en lugar de pasar HTML, pase la clase de componente. A partir de ahora, esto es un poco molesto, porque los componentes no se pueden definir en el mismo archivo. ejemplo REPL
La clave es representar los componentes dinámicamente a través de <svelte:component /> y pasar el valor de la columna actual como un accesorio conocido que es el mismo para todos los componentes de la celda.
En lugar de usar componentes, renderice HTML directamente usando {@html} . No recomiendo esto en absoluto , porque facilita la creación de vulnerabilidades XSS. ejemplo REPL
La clave aquí es proporcionar el contenido como una función del valor de la columna, así:
const columns = [ { key: 'name', html: value => `<button>${value}</button>` }, { key: 'age', html: value => `<em>${value}</em>` }, ]Entonces esto se puede representar con el valor actual de esta manera:
<td>{@html column.html(value)}</td>Si solo tiene contenido estático, no necesita una función, por supuesto.
Usa ranuras y teclas para renderizar las diferentes celdas. Este es un enfoque muy flexible que se utiliza, por ejemplo, en el DataTable de los componentes Carbon Svelte .
Las columnas definen la clave y las celdas se pueden crear mediante plantillas a través de ranuras y accesorios de ranura.
P.ej
<!-- DataTable.svelte --> <script> export let columns; export let rows; </script> <table> {#each rows as row} <tr> {#each columns as column} {@const value = row[column.key]} <td> <slot {value} key={column.key} /> </td> {/each} </tr> {/each} </table>Ejemplo de uso:
<script> import DataTable from './DataTable.svelte'; const rows = [ { name: 'John', age: 64 }, { name: 'Jane', age: 46 }, ] const columns = [ { key: 'name' }, { key: 'age' }, ] </script> <DataTable {columns} {rows} let:key let:value> {#if key == 'name'} <button>{value}</button> {:else} {value} <!-- Fallback to just the cell content --> {/if} </DataTable>