You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte 5中如何用{@render}替换嵌套组件中已弃用的<slot />?

Svelte 5中如何用{@render}替换嵌套组件中已弃用的?

嘿,我刚搞定了Svelte 5里替换<slot />的类似场景,正好和你的递归列表需求对上!我来一步步给你讲怎么改:

首先得明白Svelte 5的核心变化:原来的<slot />被废弃了,现在组件的内容(不管是默认slot还是命名slot)都要通过props传递,然后用{@render}语法来渲染。对于默认slot的内容,Svelte 5会自动把它封装成一个特殊的$children props,我们直接用{@render $children}就能替代原来的<slot />。

第一步:改造List.svelte

把原来的<slot />直接替换成{@render $children}就行,其他逻辑保持不变:

<script lang="ts">
    import type { List } from 'datocms-structured-text-utils';

    let { node }: { node: List } = $props();
    let { style } = $state(node);
</script>

{#if style === 'numbered'}
    <!-- 用{@render $children}替代<slot /> -->
    <ol>{@render $children}</ol>
{:else}
    <ul>{@render $children}</ul>
{/if}

第二步:调整+page.svelte的用法

这里注意你代码里的<Component {node}>应该是笔误,实际应该是<List {node}>对吧?保持原来的递归逻辑不变就行,因为$children会自动接收标签内部的内容(也就是你用svelte:self渲染的子节点):

<List {node}>
  {#if hasChildren(node)}
    {#each node.children as child}
      <svelte:self node={child} />
    {/each}
  {/if}
</List>

额外说明(如果以后用命名slot)

要是你以后需要用命名slot,就不能依赖$children了,得显式定义props来接收:
比如在List.svelte里声明一个header props:

<script lang="ts">
    // ... 其他代码
    let { header } = $props();
</script>

{@render header}
{#if style === 'numbered'}
    <ol>{@render $children}</ol>
{:else}
    <ul>{@render $children}</ul>
{/if}

然后在父组件里传递:

<List {node} header={<h3>我的列表标题</h3>}>
  <!-- 默认slot内容 -->
</List>

这样改完之后,你的递归列表就能和原来Svelte 4里的逻辑完全一致,同时符合Svelte 5的新语法规范啦!

备注:内容来源于stack exchange,提问作者Thomaszter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 12:49:52