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

Svelte如何实现全局/Super Slots?多页面内容聚合到命名插槽

实现方法:通过上下文API收集嵌套路由的插槽内容

Svelte默认的命名插槽在路由嵌套时,子路由的同名插槽会覆盖父级内容,没法直接实现多路由插槽内容累加。要达到需求,需要借助Svelte上下文API来收集所有嵌套路由的safely插槽内容,再在根布局统一渲染。

步骤1:创建插槽内容收集的上下文模块

新建src/lib/safeSlot.js,用来管理插槽内容的存储和操作:

import { writable } from 'svelte/store';
import { setContext, getContext } from 'svelte';

// 用Symbol作为上下文唯一标识,避免冲突
const SAFE_SLOT_KEY = Symbol('safe-slot');

// 在根布局初始化上下文
export function createSafeSlotContext() {
  const { subscribe, update } = writable([]);

  // 添加插槽内容的方法
  const addSlot = (content) => {
    update(items => [...items, content]);
    // 返回移除当前内容的函数,用于组件销毁时清理
    return () => update(items => items.filter(item => item !== content));
  };

  setContext(SAFE_SLOT_KEY, { addSlot, subscribe });
}

// 获取上下文的方法
export function getSafeSlotContext() {
  return getContext(SAFE_SLOT_KEY);
}

步骤2:修改根布局__layout.svelte

在根布局中初始化上下文,并订阅收集到的插槽内容,统一渲染:

<script>
  import { createSafeSlotContext, getSafeSlotContext } from '$lib/safeSlot';

  const hi = "hi";
  // 初始化上下文
  createSafeSlotContext();
  let safeContents = [];

  // 订阅插槽内容的变化
  const { subscribe } = getSafeSlotContext();
  subscribe(items => {
    safeContents = items;
  });
</script>

<h1>{hi}</h1>
<slot />

<!-- 渲染所有收集到的safely插槽内容 -->
{#each safeContents as content}
  {content}
{/each}

步骤3:在子路由中收集插槽内容

以./route/to/something/index.svelte为例,修改组件,将safely插槽的内容添加到上下文:

<script>
  import { getSafeSlotContext } from '$lib/safeSlot';
  import { onMount, onDestroy } from 'svelte';
  import CustomComponent from '$lib/CustomComponent.svelte';

  const { addSlot } = getSafeSlotContext();
  // 定义当前插槽的内容
  const slotContent = <CustomComponent>first</CustomComponent>;
  let removeSlot;

  onMount(() => {
    // 挂载时添加插槽内容到上下文,拿到移除函数
    removeSlot = addSlot(slotContent);
  });

  onDestroy(() => {
    // 组件销毁时移除当前插槽内容,避免路由切换后残留
    removeSlot();
  });
</script>

<p>
  in this page we have safely components
</p>

同样修改./in/another/nested/component/index.svelte:

<script>
  import { getSafeSlotContext } from '$lib/safeSlot';
  import { onMount, onDestroy } from 'svelte';
  import CustomComponent from '$lib/CustomComponent.svelte';

  const { addSlot } = getSafeSlotContext();
  const slotContent = <CustomComponent>second</CustomComponent>;
  let removeSlot;

  onMount(() => {
    removeSlot = addSlot(slotContent);
  });

  onDestroy(() => {
    removeSlot();
  });
</script>

<p>
  another safely component
</p>

说明

这种方式完全基于Svelte原生API实现,不需要额外依赖。如果是多层嵌套路由,只要每个需要贡献safely内容的路由组件都按此方式处理,根布局就能自动收集并渲染所有内容,满足你想要的累加效果。

内容的提问来源于stack exchange,提问作者Angel Ponce

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:09:19