Как нам использовать «именованные слоты» в Svelte 5?

Слоты Svelte 5 сбивают с толку

Теперь, когда Svelte 5 находится в предварительной версии, я чувствую, что могу выразить некоторую путаницу по поводу слотов в Svelte 5. В Svelte 4 слоты и названия слотов сделаны следующим образом:

ContactCard.svelte

<article class = "contact-card">
    <h2>
        <slot name = "name">
            <span class = "missing">Unknown name</span>
        </slot>
    </h2>

    <div class = "address">
        <slot name = "address">
            <span class = "missing">Unknown address</span>
        </slot>
    </div>

    <div class = "email">
        <slot name = "email">
            <span class = "missing">Unknown email</span>
        </slot>
    </div>
</article>

<style>...</style>

+page.svelte

<script>
    import ContactCard from './ContactCard.svelte';
</script>

<ContactCard>
    <span slot = "name"> P. Sherman </span>

    <span slot = "address">
        42 Wallaby Way<br />
        Sydney
    </span>
</ContactCard>

По моему скромному мнению, довольно просто и понятно.

Пример Svelte 5 с одним слотом

Component.svelte

<script>
  let { children } = $props();
</script>

<div>
  {@render children()}
</div>

+page.svelte

<script>
  import { Component } from '$lib';
</script>

<Component>
  ...content...
</Component>

Также легко...

Мой вопрос...

Как нам реализовать «именованные слоты» в этой новой парадигме?

🤔 А знаете ли вы, что...
JavaScript позволяет создавать мобильные приложения для iOS и Android с использованием фреймворков, таких как React Native и NativeScript.


1
280
1

Ответ:

Решено

Вы просто определяете #snippet внутри компонента.
Фрагмент будет передан как реквизит с тем же именем. Например.:

<script>
    import ContactCard from './ContactCard.svelte';
</script>

<ContactCard>
    {#snippet name()} P. Sherman {/snippet}

    {#snippet address()}
        42 Wallaby Way <br>
        Sydney
    {/snippet}
</ContactCard>

(Если вам нужны элементы span, вы можете добавить их внутрь фрагмента.)

<!-- ContactCard.svelte -->
<script>
  let { name, address } = $props();
</script>

<div>
  <div class = "name">{@render name()}</div>
  <div class = "address">{@render address()}</div>
</div>

Для резервного контента вы можете проверить, был ли передан фрагмент, например. используя {#if}, или определите резервный фрагмент.

<div class = "name">
    {@render name?.()}
    {#if !name}
        ...
    {/if}
</div>
<div class = "name">
    {#snippet nameUnknown()}...{/snippet}
    {@render (name ?? nameUnknown)()}
</div>

Фрагменты могут быть определены вне компонента, а также переданы явно:

{#snippet name()} P. Sherman {/snippet}
{#snippet address()}
    42 Wallaby Way <br>
    Sydney
{/snippet}
<ContactCard {name} {address} />

Определение области действия работает аналогично переменным; фрагменты доступны на том же уровне и глубже в своем элементе/блоке.


Примечание: прямое содержимое компонента просто неявно определяет фрагмент под названием children. Если вам нужно параметризовать фрагмент, вам также придется определить его более явно, например:

<FancyList items = {users}>
    {#snippet children(item)}
        {item.lastName}, {item.firstName}
    {/snippet}
</FancyList>

На этом этапе вы также можете назвать это как-нибудь более конкретно, например itemTemplate в этом примере.