mcpField
S
svelte-reference

svelte-reference

github.com/full-stack-skills开发4100 次安装5 周前更新
代码仓库

关于 svelte-reference

svelte-reference 是面向 Svelte 5 开发者的 API 参考技能,整理常用模块、指令、编译器配置及错误与警告说明。它还提供状态管理、过渡动画、列表动画和 action 的实践示例与注意事项。

主要功能

  1. 01汇总 store、action 和事件 API
  2. 02说明过渡、缓动与列表动画
  3. 03提供编译器配置和输出参考
  4. 04解释常见编译错误与运行时警告
  5. 05附带 API 示例及常见问题提示

适用场景

  1. 01查找 Svelte 模块的 API 签名
  2. 02实现组件过渡或列表重排动画
  3. 03选择 store 或 runes 管理状态
  4. 04诊断编译错误和运行时警告

安装

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

$npx skills add https://github.com/full-stack-skills/svelte-skills --skill svelte-reference

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

包含的文件

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

agents/
openai.yaml
examples/
in-out-animate.md
motion.md
README.md
store-patterns.md
transition.md
transitions-advanced.md
use-action.md
references/
animations-reference.md
in-out-reference.md
motion-reference.md
README.md
store-reference.md
transition-reference.md
transitions-complete.md
use-action-reference.md

详细介绍

Svelte API 参考(Svelte 5)

本技能是 Svelte 官方模块 API 的快速参考,包括 svelte/store、svelte/action、svelte/transition、svelte/animate、svelte/easing、svelte/events、svelte/compiler 及常见编译器/运行时错误代码。

何时使用此技能

当用户需要查阅 Svelte 特定模块的 API 签名、使用 transition / in / out / animate 指令、use: action、easing 函数、错误代码含义,或需要编译器配置时,使用本技能。

关键:svelte/store

import { writable, readable, derived, readonly, get } from 'svelte/store';
函数签名说明
writable(initial, start?) => { subscribe, set, update }可写 store
readable(initial, start) => { subscribe }只读 store(值只能由内部 start 设置)
derived(stores, fn, initial?) => { subscribe }派生 store
readonly(store) => store返回只读版本(无 set / update)
get(store) => value非订阅获取值(同步,创建临时订阅)
Store 合约
store = {
  subscribe: (subscription: (value: any) => void) => (() => void),
  set?: (value: any) => void
}
何时使用 Stores,何时使用 Runes
  • 优先使用 runes(在 .svelte.js 文件中使用 $state)来实现共享状态和提取逻辑。
  • 使用 stores 来处理复杂的异步数据流、手动控制更新,或使用 RxJS 风格的运算符。
writable 启动函数

writable(initial, start) — 当订阅者数量从 0 → 1 时(而非从 1 → 2),会调用 start 回调。返回一个 stop 函数,它会在订阅者数量从 1 → 0 时运行。start 回调还会接收一个 update 函数(除了 set),用于基于转换的更新。

derived 的形式
// single store
const doubled = derived(a, ($a) => $a * 2);

// array of stores
const sum = derived([a, b], ([$a, $b]) => $a + $b);

// async — second arg is `set`, third is `update`, third `derived` arg is initial value
const delayed = derived(a, ($a, set) => {
  setTimeout(() => set($a), 1000);
}, 0);

// with cleanup — return a function from the callback
const tick = derived(frequency, ($frequency, set) => {
  const id = setInterval(() => set(Date.now()), 1000 / $frequency);
  return () => clearInterval(id);
}, 0);
get(store) 注意事项

它会创建临时订阅,读取值,然后取消订阅。避免在热点路径中使用。

关键:svelte/action(use: 指令)

Action 是在元素挂载时调用的函数,通过 use: 指令添加:

<script>
  /** @type {import('svelte/action').Action} */
  function myAction(node) {
    // node: HTMLElement — runs once on mount (client only, not SSR)
    $effect(() => {
      // setup
      return () => {
        // teardown — runs on unmount
      };
    });
  }
</script>

<div use:myAction>...</div>

说明

在 Svelte 5.29 及更高版本中,可以考虑改用 {@attach ...}——它更灵活,也更易组合。

带参数的 Action

参数不是响应式的——Action 只会在挂载时运行一次。可在内部使用 $effect 来响应参数变化。

<script>
  /** @type {import('svelte/action').Action<HTMLInputElement, number>} */
  function debounce(node, delay) {
    $effect(() => {
      const handler = () => setTimeout(() => node.dispatchEvent(new Event('done')), delay);
      node.addEventListener('input', handler);
      return () => node.removeEventListener('input', handler);
    });
  }
</script>

<input use:debounce={300} />
旧版 update / destroy 形式
<script>
  /** @type {import('svelte/action').Action<HTMLDivElement, string>} */
  function colorize(node, color) {
    node.style.color = color;
    return {
      update(newColor) { node.style.color = newColor; },
      destroy() { node.style.color = ''; }
    };
  }
</script>

<div use:colorize={'red'}>...</div>

新代码优先使用 $effect 形式。

类型标注——Action<Node, Parameter, Events>
<script lang="ts">
  import type { Action } from 'svelte/action';

  const gestures: Action<HTMLDivElement, undefined, {
    onswipeleft: (e: CustomEvent) => void;
    onswiperight: (e: CustomEvent) => void;
  }> = (node) => {
    // dispatch: node.dispatchEvent(new CustomEvent('swipeleft'));
  };
</script>

<div use:gestures onswipeleft={next} onswiperight={prev}>...</div>

第三个类型参数可让模板中的 onswipeleft / onswiperight 通过类型检查。

关键:svelte/transition(transition: 指令)

<script>
  import { fade, fly, slide, scale, blur, draw, crossfade } from 'svelte/transition';
</script>

{#if visible}
  <div transition:fade={{ duration: 300, delay: 100 }}>fade</div>
  <div transition:fly={{ y: 20, duration: 300 }}>fly</div>
  <div transition:slide>slide</div>
  <div transition:scale={{ start: 0.5, duration: 300 }}>scale</div>
  <div transition:blur={{ amount: 10 }}>blur</div>
{/if}

transition: 是双向的——被中断时会反向运行。

内置过渡效果
函数效果关键参数
fade透明度duration
fly位置飞入x、y、opacity
slide滑动axis: 'x' | 'y'
scale缩放start、opacity
blur模糊 + 透明度amount
drawSVG 路径绘制speed 或 duration
crossfade成对淡入淡出duration、fallback
过渡参数
{
  delay?: number,        // ms before starting (default 0)
  duration?: number,     // ms (default 400)
  easing?: function,     // easing (default linear)
  css?: (t, u) => string,// web animation CSS (preferred)
  tick?: (t, u) => void  // imperative (use only when CSS cannot)
}

在 intro 时,t 从 0 → 1 运行;在 outro 时,t 从 1 → 0 运行。u = 1 - t。在 t 传给 css / tick 之前,会应用缓动。css 和 tick 不能同时使用。

局部与全局

<div transition:fade>...</div>


<div transition:fade|global>...</div>
过渡事件
事件触发时机
introstartintro 动画开始前
introendintro 动画结束后
outrostartoutro 动画开始前
outroendoutro 动画结束后
<div
  transition:fly={{ y: 200, duration: 2000 }}
  onintrostart={() => (status = 'intro started')}
  onoutroend={() => (status = 'outro ended')}
>...</div>
自定义过渡函数
// @noErrors
transition = (
  node: HTMLElement,
  params: any,
  options: { direction: 'in' | 'out' | 'both' }
) => {
  delay?: number;
  duration?: number;
  easing?: (t: number) => number;
  css?: (t: number, u: number) => string;
  tick?: (t: number, u: number) => void;
}

如果函数返回的是一个函数(而不是对象),Svelte 会在下一个微任务中调用它——crossfade 就是用这种方式协调成对的过渡效果。

重要:in: 和 out:(独立过渡)

in: 和 out: 是单向的——中断时不会反转。如果在入场动画中途切换关闭代码块,正在进行的入场动画会被放弃,出场过渡会从 t=0 重新开始。

<script>
  import { fade, fly } from 'svelte/transition';
  let visible = $state(false);
</script>

{#if visible}
  
  <div in:fly={{ y: 200 }} out:fade>...</div>
{/if}
指令运行时机中断时可反转?
transition:进入或离开时可以(中途反转)
in:仅进入时不可以(放弃)
out:仅离开时不可以(始终正向播放)

当进入和退出动画在视觉上应有所不同时,使用 in: / out:。自定义过渡函数的第三个参数是 { direction: 'in' | 'out' | 'both' }。

重要:svelte/easing

import { cubicIn, cubicOut, cubicInOut, elasticOut, bounceOut } from 'svelte/easing';
缓动说明
linear匀速
quadIn/quadOut/quadInOut二次
cubicIn/cubicOut/cubicInOut三次缓动
quartIn/quartOut/quartInOut四次
quintIn/quintOut/quintInOut五次
sineIn/sineOut/sineInOut正弦
expoIn/expoOut/expoInOut指数
circIn/circOut/circInOut圆
elasticIn/elasticOut/elasticInOut弹性
backIn/backOut/backInOut回退
bounceIn/bounceOut/bounceInOut弹跳
<div transition:fly={{ y: 100, easing: cubicOut }}>...</div>

重要:animate:(svelte/animate)

animate: 会在带键的 {#each} 代码块中,现有项的索引发生变化时运行,而不是在添加/移除项时运行。它必须放在带键 each 代码块的直接子元素上。

<script>
  import { flip } from 'svelte/animate';
  let items = $state(['apple', 'banana', 'cherry']);
</script>

{#each items as item (item)}
  <li animate:flip={{ duration: 400, easing: quintOut }}>{item}</li>
{/each}
flip(FLIP 技术)

测量 from 和 to 边界矩形,应用反向 transform,然后再将其动画回初始状态。完整 API 请参阅 references/animations-reference.md。

flip(node, {
  delay?: number,
  duration?: number | (node, { from, to }) => number,
  easing?: function
})
自定义动画函数
// @noErrors
animation = (
  node: HTMLElement,
  { from: DOMRect, to: DOMRect },
  params: any
) => {
  delay?: number;
  duration?: number;
  easing?: (t: number) => number;
  css?: (t: number, u: number) => string;
  tick?: (t: number, u: number) => void;
}

from 和 to 分别是重排前后元素的边界矩形。计算距离、角度等,以驱动自定义效果:

<script>
  import { cubicOut } from 'svelte/easing';

  function whizz(node, { from, to }) {
    const dx = from.left - to.left;
    const dy = from.top - to.top;
    const d = Math.sqrt(dx * dx + dy * dy);
    return {
      duration: Math.sqrt(d) * 120,
      easing: cubicOut,
      css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);`
    };
  }
</script>

{#each list as item (item)}
  <div animate:whizz>{item}</div>
{/each}

animate: 不会在添加/移除项时运行——此时请结合使用 in: / out:。

重要:svelte/events

提供 on 函数,用于替代 addEventListener(正确处理事件委托和 stopPropagation):

<script>
  import { on } from 'svelte/events';

  const handler = on(node, 'click', (event) => {
    // 正确处理委托和 stopPropagation
  }, { passive: true });
</script>

重要:svelte/reactivity

$effect.tracking
$effect.tracking(); // boolean,是否在追踪上下文中
createSubscriber

创建订阅者(仅在追踪上下文中工作):

import { createSubscriber } from 'svelte/reactivity';
const subscriber = createSubscriber((track) => {
  track(value); // 声明依赖
});

重要:编译器错误(常见)

代码含义解决方法
2304未定义的引用检查变量名拼写和导入
2322目标元素不存在检查 target selector
2554类型不匹配检查 TypeScript 类型标注
2451在非 effect 中修改 state不要在 $effect 中直接赋值 $state
7006参数类型错误检查函数签名

重要:运行时警告(常见)

代码含义解决方法
ownership_invalid_mutation修改了非自有状态不要直接修改 prop,使用 $bindable
await_waterfallawait 依赖链导致性能问题重构数据获取逻辑
state_teardown尝试在销毁后更新确保组件未卸载后再访问

重要:svelte/compiler

配置项
import { compile } from 'svelte/compiler';
const result = compile(source, {
  filename: 'App.svelte',
  generate: 'dom',       // 'dom' | 'ssr' | false
  name: 'Component',      // 导出名
  format: 'esm',         // 'esm' | 'cjs'
  sveltePath: 'svelte',  // svelte 包路径
  dev: true,             // 开发模式(添加检查)
  css: 'injected',       // CSS 注入方式
  runes: false,           // 强制 Legacy Mode
  // ...
});
compile 输出
result.js.code;      // 编译后的 JS
result.css.code;     // 编译后的 CSS(如有)
result.warnings;     // 警告列表
result.stats;        // 编译统计

快速修复

问题解决方法
过渡不触发确认条件块变化时元素被销毁/重建;使用 {#key}
in:/out: 中途切换行为奇怪这是单向行为的预期结果——只有 transition: 可反转
animate:flip 不工作必须有 (key),且 animate: 必须放在带键 each 代码块的直接子元素上
flip 动画不流畅确保 key 唯一且稳定
缓动函数不工作确认已从 svelte/easing 正确导入
use: 参数变化不生效action 只调用一次;在 $effect 内部读取参数
编译器报错查看上方的错误代码表
运行时警告检查所有权链

示例

附有详细说明的实用用法模式:

参考

完整的 API 文档:

注意事项

  1. svelte/transition 的 css 和 tick 互斥 — 两者只能用一个
  2. in: / out: 不可逆 — 中断时会放弃进行中的 intro,outro 会从 t=0 重新开始
  3. animate: 必须位于 keyed each 的直接子元素上 — 嵌套 div 上的 animate: 不会运行
  4. flip 需要稳定的 key — 使用唯一 ID,而非数组索引
  5. animate: 不会响应添加/移除 — 只会在重新排序时触发
  6. Store subscribe 会返回 unsubscribe 函数 — 组件卸载时会自动取消订阅
  7. get(store) 会创建临时订阅 — 频繁调用会影响性能
  8. elasticIn/elasticOut 较慢 — 大量使用可能会影响性能
  9. use:action 参数变化时不会重新调用 — 在 action 内部使用 $effect 响应变化

评论

支持 Markdown