full-stack-skills/svelte-skills

svelte-reference

Svelte 5 API 参考技能。当用户需要查阅 svelte/action、svelte/store、svelte/transition、svelte/animate、svelte/easing、svelte/compiler、svelte/events 的具体 API,或需要查看编译器错误/警告代码时使用。

查看源码

使用方法

  1. 复制安装命令,在自己的智能体环境安装前先检查源码包。
  2. 从原始文档核对所需工具、凭据和支持的宿主。
  3. 说明输入材料与期望交付物,并对照来源检查输出。
npx skills add https://github.com/full-stack-skills/svelte-skills --skill svelte-reference

开始前需了解

  • 安装不包含模型订阅、API 额度或访问文件的权限。
  • 仓库星数和安装量反映活跃情况,不等于独立质量或安全测试。
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

Svelte API Reference (Svelte 5)

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

When to use this skill

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

Critical: svelte/store

js
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 Contract

ts
store = {
  subscribe: (subscription: (value: any) => void) => (() => void),
  set?: (value: any) => void
}

When to Use Stores vs Runes

  • Prefer runes ($state in .svelte.js files) for shared state and logic extraction.
  • Use stores when you have complex async data streams, need manual control over updates, or want RxJS-style operators.

writable Start Function

writable(initial, start) — the start callback is called when the subscriber count goes 0 → 1 (not 1 → 2). Return a stop function that runs when subscribers go 1 → 0. The start callback also receives an update function (in addition to set) for transform-based updates.

derived Forms

js
// 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) Caveat

Creates a temporary subscription, reads, then unsubscribes. Avoid in hot paths.

Critical: svelte/action (use: directive)

Actions are functions called when an element is mounted, added with the use: directive:

svelte
<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>
[!NOTE] In Svelte 5.29 and newer, consider using `{@attach ...}` instead — more flexible and composable.

Action With Parameter

The parameter is not reactive — the action runs once on mount. Use $effect inside to react to parameter changes.

svelte
<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} />

Legacy update/destroy Form

svelte
<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>

Prefer the $effect form for new code.

Typing — Action<Node, Parameter, Events>

svelte
<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>

The third type parameter makes onswipeleft / onswiperight type-check in the template.

Critical: svelte/transition (transition: directive)

svelte
<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: is bidirectional — reverses on interrupt.

Built-in Transitions

函数效果关键参数
fade透明度duration
fly位置飞入x, y, opacity
slide滑动`axis: 'x' \'y'`
scale缩放start, opacity
blur模糊 + 透明度amount
drawSVG 路径绘制speed or duration
crossfade成对淡入淡出duration, fallback

Transition Parameters

ts
{
  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)
}

t runs 0 → 1 on intro, 1 → 0 on outro. u = 1 - t. Easing is applied to t before it reaches css / tick. `css` and `tick` are mutually exclusive.

Local vs Global

svelte
<!-- local: only animates when this block is created/destroyed -->
<div transition:fade>...</div>

<!-- global: animates whenever ANY ancestor block toggles -->
<div transition:fade|global>...</div>

Transition Events

EventFires
introstartbefore intro animation
introendafter intro animation
outrostartbefore outro animation
outroendafter outro animation
svelte
<div
  transition:fly={{ y: 200, duration: 2000 }}
  onintrostart={() => (status = 'intro started')}
  onoutroend={() => (status = 'outro ended')}
>...</div>

Custom Transition Function

ts
// @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;
}

If the function returns a function (instead of an object), Svelte calls it in the next microtask — this is what crossfade uses to coordinate paired transitions.

Critical: in: and out: (separate transitions)

in: and out: are unidirectional — they do not reverse on interrupt. If you toggle a block off mid-intro, the in-flight intro is abandoned and the out-transition restarts from t=0.

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

{#if visible}
  <!-- flies in, fades out — NOT a reversible fly/fade -->
  <div in:fly={{ y: 200 }} out:fade>...</div>
{/if}
DirectiveWhen it runsReversible on interrupt?
transition:enter or leaveyes (reverses mid-flight)
in:enter onlyno (abandoned)
out:leave onlyno (always plays forward)

Use in: / out: when enter and exit animations should be visually different. The third argument to a custom transition function is { direction: 'in' | 'out' | 'both' }.

Critical: svelte/easing

js
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弹跳
svelte
<div transition:fly={{ y: 100, easing: cubicOut }}>...</div>

Critical: animate: (svelte/animate)

animate: runs when the index of an existing item changes inside a keyed {#each} block — not on add/remove. It must be on the immediate child of a keyed each block.

svelte
<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 technique)

Measures from and to bounding rects, applies an inverse transform, then animates back to identity. See references/animations-reference.md for full API.

ts
flip(node, {
  delay?: number,
  duration?: number | (node, { from, to }) => number,
  easing?: function
})

Custom Animation Function

ts
// @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 and to are the element's bounding rects before and after the reorder. Compute distance, angle, etc. to drive custom effects:

svelte
<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: does not run on add/remove — combine with in: / out: for those.

Critical: svelte/events

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

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

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

Critical: svelte/reactivity

$effect.tracking

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

createSubscriber

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

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

Critical: Compiler Errors (常见)

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

Critical: Runtime Warnings (常见)

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

Critical: svelte/compiler

配置项

js
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 输出

js
result.js.code;      // 编译后的 JS
result.css.code;     // 编译后的 CSS(如有)
result.warnings;     // 警告列表
result.stats;        // 编译统计

Quick Fixes

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

Examples

Practical usage patterns with detailed explanations:

References

Complete API documentation:

Gotchas

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

更多 Skills

全部 Skills