mcpField
S
svelte

svelte

github.com/epicenterhq开发4.8k192 次安装3 周前更新
代码仓库

关于 svelte

面向特定项目的 Svelte 5 开发指南,涵盖组件、响应式、生命周期和 UI 组合,适用于该工作区的开发者,并强调对关键行为变更核查上游资料。

主要功能

  1. 01Svelte 5 runes 与响应式指南
  2. 02组件属性、片段和事件模式
  3. 03生命周期与异步资源模式
  4. 04响应式集合和存储集成指南
  5. 05TanStack Query mutation 约定
  6. 06上游源码核验指南

适用场景

  1. 01实现或更新 Svelte 组件
  2. 02选择状态和生命周期模式
  3. 03将工作区数据接入响应式 UI
  4. 04核实影响行为的 Svelte API 变更

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/epicenterhq/epicenter --skill svelte

安装后在 Claude Code 中输入/svelte确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
component-ui-patterns.md
input-ownership.md
lifecycle-and-reactivity.md
mutations-and-workspace-inputs.md

详细介绍

Svelte 指南

首轮重点关注 Svelte 符文、组件生命周期、由工作区支持的状态、TanStack Query 用法和本地 UI 组合。

参考仓库

源码检查

上游依据

当 Svelte 5 符文、编译器行为、生命周期、响应性、片段或模板行为会影响正确性时,应先基于源码确认,不要仅凭记忆。如果 DeepWiki MCP 可用,请针对 sveltejs/svelte 提出范围明确的问题;对于 SvelteKit 集成,请针对 sveltejs/kit 提问;对于 shadcn-svelte 或 extras 组件 API,请针对 huntabyte/shadcn-svelte 或 ieedan/shadcn-svelte-extras 提问。如果 DeepWiki 不可用或仓库未建立索引,请直接使用上游源码或官方文档。将 DeepWiki 作为了解方向的起点,然后在更改代码前,根据本地已安装的类型、源码或官方文档核实关键细节。

对于稳定的基础知识以及此处或参考资料中已有文档记录的仓库本地模式,无需使用 DeepWiki。

相关技能

  • query-layer:TanStack Query 集成
  • error-handling:在操作过程中传递 Results,然后在交互边界呈现结果;包括带标签的错误和 $lib/report
  • styling:CSS 和 Tailwind 约定,包括弹性列滚动陷阱
  • ui-design:视觉方向,以及加载、空状态、待处理状态、工具提示和组件选择模式

Svelte 5 基准

  • 对组件会原地修改的响应式值,使用 $state。对于只会整体重新赋值的值(大型数组、仅通过替换更新的持久化存储、不透明句柄),使用 $state.raw:它按引用存储,不创建深层代理,不会冻结值,且仅在重新赋值时触发响应式更新。因此,原地修改属性会改变对象,但不会触发响应式更新或持久化(这不是错误,只是不具备响应式)。当深层代理带来的响应式能力用不上,且稳定的值标识很重要时(例如,值会被 JSON 序列化或按引用比较的存储),可考虑使用它。示例:packages/svelte 中的 createPersistedState。
  • 优先使用 $derived 来计算状态。将 $effect 视为仅限浏览器的备用手段,用于 DOM 集成、分析、订阅和外部系统。返回的清理函数会在 effect 重新运行前以及组件销毁时执行。
  • Props 可能会变化。使用 $derived 计算会变化的值,或在使用处直接读取 prop。仅当适配器的归属在该组件实例中固定时,才只初始化一次;响应式属性并不意味着适配器标识会变化。阅读生命周期与响应式。
  • 默认将 props 视为由父组件拥有。使用回调 prop 执行操作,仅在有意提供双向 API 时使用 $bindable,例如 UI 包装器、bind:value、bind:open 和 bind:ref。对于受控输入,优先使用 bind:value={get, set},而非成对的读写 props;参见函数绑定。
  • 对于新的 Svelte 5 代码,优先使用 snippets 和 {@render},而非 slots。使用 svelte 中的 Snippet 为暴露的 snippet props 指定类型;使用 Snippet<[Row]> 这类元组参数。
  • 在 rune 模式代码中,避免使用旧式模式:$: 声明、export let、on:click、<slot>、<svelte:component>、<svelte:self>、beforeUpdate、afterUpdate 和 createEventDispatcher。
  • 使用事件属性和回调 props,例如 onclick={...}、onkeydown={...} 和 onSelect={() => ...} 风格的 props。不要在新的 rune 模式代码中添加 on: 指令或派发组件事件。

核心决策

  • 在添加内容状态之前,先选择即时编辑还是显式提交。即时控件绑定到当前编辑器,并提交完整替换内容。显式表单为每次提交维护一份草稿,最好使用通过替换更新的 $state.raw 对象;普通代理式 $state 在其 API 边界需要纯数据时使用 $state.snapshot。请求、选择和控件状态应与此选择分开处理。
  • 如果一次性资源的身份取决于 prop,就让父组件通过 {#key} 或 {#if} 管理挂载和卸载;在子组件中同步打开资源。参阅生命周期与响应性。
  • 如果就绪状态由一个稳定的 promise 决定,就在模板中使用 {#await},而不是使用 $state(false) 标志和取消 effect。
  • 让数据读取和操作在使用处一目了然:在标记中直接读取 session.current 或 editor.row 等所有者属性,并在控件旁内联编写转发处理器;当简短的守卫能说明交互时,也应一并写出。若名称能说明大量工作或承载必要行为(包括将通知筛选到 effects),则保留该名称。参阅组件与 UI 模式和生命周期与响应性。
  • 使用 satisfies Record 查找表映射有限联合类型,不要使用嵌套三元表达式或 $derived.by() 分支。
  • 对按 ID 索引、且希望 get、has、size 或迭代操作能触发响应式更新的集合,使用 SvelteMap。SvelteMap 中的值不会进行深度代理,因此应存储响应式行对象,或在嵌套数据变化时替换值。将映射转换为稳定数组后,再通过 $derived 传给表格类使用方。
  • 对 ID 集合使用 SvelteSet,前提是其成员关系(has、size、迭代)会在响应式或模板上下文中读取:使用 add/delete 直接驱动 UI,取代 $state<string[]> 加展开/筛选后重新赋值。一旦集合需要携带每个键的数据(时间戳、最近一次错误),就改用 SvelteMap。当集合只在命令式代码中读取时(例如订阅的监听器集合),使用普通 Set/Map,而非响应式类:在任何 effect 之外读取响应式包装器,只会带来开销,却没有读取者(示例:createPersistedState 中的普通 listeners 集合)。
  • 通过 @epicenter/svelte 中的 fromData 读取 Epicenter 存储数据:它会映射已打开数据库声明的 tables/kv 以及 persistence,让每次读取都具有响应性,并将写入传递到底层。表会作为按行 ID 索引的实时 SvelteMap 投影保留:对于原始存储,在首次调用 fromData 时初始化;之后每次提交时根据提交中列出的 ID 更新。对同一原始存储的后续调用会返回相同投影,不会遍历表或再次订阅;即使某个已声明表没有任何内容要渲染,也会在首次调用时遍历;kv 和 persistence 则通过 createSubscriber 保持直读。无需拆除任何内容,也无需手动释放任何内容:投影会随文档一同销毁。读取表数据时,不要手动编写 db.<table>.subscribe(listener),再将数据写入 $state.raw;使用 $derived 对 table.rows 进行筛选和排序。若要读取非表数据源中的单个值,请使用 fromSubscription(subscribe, read),不要手动编写 createSubscriber。适配器:packages/svelte/src/from-data.svelte.ts;应用示例:apps/honeycrisp/src/routes/components/Notes.svelte。
  • 对于非存储的外部事件源(window 事件、auth 存储),使用 svelte/reactivity 中的 createSubscriber 将其接入响应式系统,不要手动编写 $state、$effect 和监听器集合:effect 内的读取会变为响应式,且订阅会按 effect 使用情况进行引用计数(首个订阅者到来时启动,订阅者归零时清理)。示例:packages/auth/src/svelte/auth.svelte.ts。只有在同一数据源还为命令式 .get()/.watch() 使用方提供服务,且其生命周期无法依赖 effect 引用计数时,才保留手动监听器集合(同样参见 createPersistedState)。
  • 为元素创建可复用的 DOM 行为时,优先使用 {@attach} attachments,而非新增 use: actions。已有代码或仅提供 actions 的库可继续使用 use:。
  • 在 .svelte 文件中创建 TanStack Query mutations;除非某项操作值得封装成语义明确的辅助函数,否则直接从模板处理器调用 mutation.mutate(...)。参阅mutations 与工作区输入。
  • 关于旧版 Y.Map 值字段,请参阅mutations 与工作区输入中的失焦时提交策略。不要将该策略用于 Folder 行编辑器;它们会立即接受输入,并自行管理发布队列。
  • 对于将纯文本与表达式组合的字符串属性,使用 Svelte 引号插值(label="Loading {name}"、href="/users/{id}"),不要使用 JavaScript 模板字面量属性。非字符串值、回调、对象、布尔值,以及整个属性都是计算所得 JavaScript 表达式的情况,仍使用表达式属性。
  • 对于文件编辑器视图,请遵循编辑器所有权模式:Files 打开全文,产品列表打开结构化控件,无效文件则提供明确的修复路径。按获取到的编辑器身份对详情进行键控。共享文本控件会停用已销毁的绑定;已接受的输入和保存由视图上方的所有者负责。
  • 将简单的组件 props 内联编写。只有在包装组件、泛型关系、导出契约或原生 DOM 类型组合确有需要时,才使用命名的 Props。将较大的视图模式分支拆分到职责明确的子组件中。参阅组件与 UI 模式。
  • 优先使用本地 @epicenter/ui 加载、空状态、待处理状态和工具提示组件,不要临时编写标记。

参考索引

  • 当变更涉及带键的资源、就绪状态 Promise、$effect 清理、浅层别名、值映射、SvelteMap、表格状态或 .svelte.ts 状态模块时,请阅读 生命周期与响应性。
  • 当变更涉及 TanStack Query mutation 的放置位置、内联处理程序、异步按钮状态、直接 await 或由工作区提供支持的文本输入时,请阅读 变更与工作区输入。
  • 当变更涉及 shadcn-svelte 导入、$props 类型、$bindable、片段、DOM 附加项、自包含对话框、视图分支、重复标记、内联仅使用一次的辅助函数、加载或空状态、属性优先派生或模板文本注意事项时,请阅读 组件与 UI 模式。

评论

支持 Markdown