将组件反应到 SvelteKit - 属性(JSX 渲染)中具有 HTML 的对象到脚本标记

React Components to SvelteKit - Objects with HTML in attribute (JSX rendering) to Script tag

自从我将 React 项目更改为 SvelteKit 后,我​​遇到了一个让我很好奇的特定情况。

假设我在 React 中确实有一个组件接收对象 columnsMockExample 作为道具,例如,并在对象内部消耗一个 HTML,如:

const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }]
<ColumnsComponent columnsProp={columnsMockExample}/>

因此,在 React 中,我们可以映射此对象以使用它并显示 columnsMockExample 内的每个 .html

{props.columnsProp.map((columnFromMockExample) => columnFromMockExample.html)};

那么,问题来了:由于 SvelteKit 除了 HTML 之外还有 <script/> 标签,我如何在 SvelteKit[=17] 中创建我的对象 columnsMockExample =] 标签因为它不是 JSX?

错误的SvelteKit脚本示例如下:

<script> 
  const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }] 
</script>

谢谢。

如果是纯 HTML(没有 Svelte-specific 代码,只有原始 HTML),您可以使用 @html 指令:

<script> 
  const columnsMockExample = [{name: 'Column 1', html: '<div>Inner HTML example</div>' }] 
</script>

{#each columnsMockExample as example}
  {@html example.html}
{/each}

文档:https://svelte.dev/docs#template-syntax-html

如果其中有 Svelte 组件或点击处理程序等,那将不起作用。在那种情况下,您需要使用组件和插槽 (https://svelte.dev/docs#template-syntax-slot) and/or the svelte:component tag (https://svelte.dev/docs#template-syntax-svelte-component) 重写代码——具体如何取决于您的目标。

这里可以采用几种不同的方法,所有方法都有点不同。

  1. 使用插槽让每列呈现一个单元格并通过父组件插槽呈现整行。例子可见.

  2. 定义单独的组件,而不是传递 HTML,而是传递组件 class。到目前为止,这有点痛苦,因为不能在同一个文件中定义组件。 REPL example

    关键是通过 <svelte:component /> 动态呈现组件,并将当前列值作为 well-known 属性传递,这对所有单元格组件都是相同的。

  3. 而不是使用组件实际渲染 HTML 直接使用 {@html}。我绝对不推荐这个,因为它很容易产生XSS漏洞。 REPL example

    这里的关键是提供内容作为列值的函数,如下所示:

     const columns = [
         { key: 'name', html: value => `<button>${value}</button>` },
         { key: 'age', html: value => `<em>${value}</em>` },
     ]
    

    因此可以像这样使用当前值呈现:

    <td>{@html column.html(value)}</td>
    

    如果只有静态内容,当然不需要函数。

  4. 使用插槽和键渲染不同的单元格。这是一种非常灵活的方法,例如用于通过 Carbon Svelte components.

    DataTable

    列定义键,单元格可以通过插槽和插槽道具进行模板化。

    例如

    <!-- 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>
    

    用法示例:

     <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>
    

    REPL