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

SvelteKit中如何从页面加载数据创建可写Svelte Store

解决方案:创建请求隔离的共享Store

针对你遇到的问题,核心痛点是服务端单例Store会跨请求共享数据,同时需要Store能被站点多组件复用,且支持客户端精细化修改。下面是具体实现方案:

1. 写一个Store工厂函数

不要直接创建单例Store,而是用工厂函数生成实例,确保服务端每个请求有独立Store,客户端保持单例。

新建$lib/stores/rates.js:

import { writable } from 'svelte/store';

export function createRatesStore(initialData) {
  const { subscribe, set, update } = writable(initialData);

  return {
    subscribe,
    set,
    update,
    // 可添加自定义业务方法,比如批量更新
    updateRates: (newRates) => set({ ...$ratesStore, ...newRates })
  };
}

2. 在根布局初始化并注入上下文

在根+layout.svelte中,用服务端加载的初始数据创建Store,再通过Svelte的上下文传递给所有子组件:

<script>
  import { setContext } from 'svelte';
  import { createRatesStore } from '$lib/stores/rates';
  // 接收+layout.server.js返回的初始数据
  export let data;

  // 服务端每个请求会生成新Store实例,客户端仅初始化一次
  const ratesStore = createRatesStore(data.rates);
  // 将Store注入上下文,全局可访问
  setContext('ratesStore', ratesStore);
</script>

<slot />

根+layout.server.js保持原有数据加载逻辑即可:

export async function load({ depends }) {
  depends('data:rates'); // 仅当需要主动失效数据时保留
  const rates = await fetch('你的数据源').then(res => res.json());
  return { rates };
}

3. 在任意组件中使用Store

所有需要用到数据的组件,通过getContext获取Store实例,服务端会自动绑定当前请求的实例,客户端则复用单例:

<script>
  import { getContext } from 'svelte';
  const ratesStore = getContext('ratesStore');
</script>

<!-- 订阅数据 -->
<div>美元汇率:{$ratesStore.usd}</div>

<!-- 客户端自定义时机修改数据 -->
<button on:click={() => ratesStore.set({ usd: 7.3 })}>手动更新汇率</button>

4. 客户端精细化控制示例

如果需要从API重新拉取数据并更新,完全不需要依赖load函数或depends,直接在组件里实现:

<script>
  const ratesStore = getContext('ratesStore');

  async function refreshRates() {
    const res = await fetch('/api/latest-rates');
    const latestRates = await res.json();
    ratesStore.set(latestRates);
  }
</script>

<button on:click={refreshRates} disabled={$ratesStore.isLoading}>
  {$ratesStore.isLoading ? '刷新中...' : '刷新最新汇率'}
</button>

为什么之前的方案有问题?

  • 直接导入单例Store并调用.set():服务端的Store是全局共享的,所有用户请求会共用同一实例,导致数据交叉污染。
  • 使用depends('data:rates'):这是用来标记数据依赖,触发invalidate时重新运行服务端load函数,不是客户端直接修改数据的方案,自然无法精细化控制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:56:23