在 Svelte 中传递组件列表

Passing a list of components in Svelte

我正在用 svelte 创建一个 Row 组件,它可以容纳任意数量的单元格。

这个有效:

<Row
  header
  cells={["First", "Second"]}
/>

这样做:

<Row
  header
  cells={["1", "2", "3", "4"]}
/>

但是,有没有一种方法可以传递自定义组件而不是原始值?以下导致语法错误(我可以在 JSX 中执行此操作):

<Row
  header
  cells={[<div />, <button />, <span />]}
/>

编辑:

这是我的行代码

<script lang="ts">
  export let cells
  export let widths
  export let header

  const sum = widths.reduce((a, b) => a + b, 0)
  for (let i = 0; i < widths.length; i++ ){
    console.log(widths[i] / sum * 100)
  }
</script>

<div class="row" class:header>
  {#each cells as cell, i}
    <div class="cell" style={`width: ${widths[i] / sum * 100}%`}>
      { cell }
    </div>
  {/each}
</div>

这就是我想出的“解决方案”。不是最好的,但会满足我的需要。

    <script lang="ts">
      export let cells
      export let widths
      // The amount of cells in the 
      export let header

      const sum = widths.reduce((a, b) => a + b, 0)
      for (let i = 0; i < widths.length; i++ ){
        console.log(widths[i] / sum * 100)
      }
    </script>

    <div class="row" class:header>
      <!-- 
        The reason this is like this is because Svelte can't handle dynamic slots,
        and doesn't support passing components by reference like in jsx. If we ever need
        more columns, then we can just copy and add more. It's just an unrolled for:
      -->
      {#if widths[0] !== undefined}
        <div class="cell" style={`width: ${widths[0] / sum * 100}%`}>
          <slot name="0"> </slot>
        </div>
      {/if}

      {#if widths[1] !== undefined}
        <div class="cell" style={`width: ${widths[1] / sum * 100}%`}>
          <slot name="1"> </slot>
        </div>
      {/if}

      {#if widths[2] !== undefined}
        <div class="cell" style={`width: ${widths[2] / sum * 100}%`}>
          <slot name="2"> </slot>
        </div>
      {/if}

// And so on...

<style>
  .row {
    display: flex;
    width: 100%;
    border-bottom: 1px solid #ccc;
  }

  .cell {
    padding: 10px;
    background-color: white;
  }

  .header {
    font-weight: bold;
  }

  .cell:nth-child(even) {
    background-color: #f7f7f7;
  }

</style>

你可以使用<svelte:component>标签,但你必须换个思路。

将您的单元格想象成这样定义:

interface Cell {
  value?: any;
  component?: SvelteComponent;
}

那么你的Row可以这样实现:

<script lang="ts">
  export let cells
  export let widths
  export let header

  const sum = widths.reduce((a, b) => a + b, 0)
  for (let i = 0; i < widths.length; i++ ){
    console.log(widths[i] / sum * 100)
  }
</script>

<div class="row" class:header>
  {#each cells as cell, i}
    <div class="cell" style={`width: ${widths[i] / sum * 100}%`}>
      {#if cell.component}
        <svelte:component this={cell.component} value={cell.value}/>
      {:else}
        {cell.value}
      {/if}
    </div>
  {/each}
</div>