Skip to main content

svelte-legacy-apis

Svelte 5 Legacy API 技能。当用户需要维护或迁移 Svelte 4 代码,理解 Reactive let/$:/export let/Slots/createEventDispatcher/$$props 等已废弃但仍可用的 Legacy API 时使用。

설치로 이동

소스 정보

저장소
full-stack-skills/svelte-skills
최근 소스 활동
2026년 9월 11일 13:43
감지된 SKILL.md 언어
중국어
스타
3
포크
2

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
11 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
svelte-legacy-apis
license
Apache-2.0
description
Svelte 5 Legacy API 技能。当用户需要维护或迁移 Svelte 4 代码,理解 Reactive let/$:/export let/Slots/createEventDispatcher/$$props 等已废弃但仍可用的 Legacy API 时使用。
# Svelte Legacy APIs Reference (Svelte 4 → Svelte 5) 本技能覆盖 Svelte 4 的 Legacy API,这些 API 在 Svelte 5 中仍可用(Legacy Mode),但推荐迁移到 Runes。本技能仅用于理解和迁移 Legacy 代码,**新代码应使用 Runes**。 ## When to use this skill 当用户需要维护 Svelte 4 项目、理解 `$:` reactive 语句、`export let` props、`createEventDispatcher`、Slots、或需要将 Legacy 代码迁移到 Svelte 5 Runes Mode 时使用本技能。 ## Critical: Reactive let declarations 在 Legacy Mode(未使用 Runes 的组件),顶层 `let` 声明自动成为响应式: ```svelte <script> let count = 0; // 自动响应式 </script> <button on:click={() => count++}> {count} </button> ``` > Svelte 5 的 Runes Mode:`let count = $state(0)`。 ### 数组/对象变更注意 Legacy 响应式基于**赋值**,数组方法(`.push()`、`.splice()`)不触发更新: ```svelte <script> let items = [1, 2, 3]; function addItem() { items.push(4); // ❌ 不触发更新 items = items; // ✅ 触发 // 或 items = [...items, 4]; // ✅ 触发 } </script> ``` ## Critical: Reactive $: statements 在 Legacy Mode,`$:` 标签语句创建响应式语句: ```svelte <script> let a = 1; let b = 2; $: sum = a + b; // 依赖 a, b $: console.log(`sum = ${sum}`); // 依赖 sum </script> ``` ### 拓扑排序 `$:` 语句按依赖拓扑排序(顺序无关): ```svelte $: z = y; // z 依赖 y $: y = x; // y 依赖 x $: x = 5; // x 无依赖 ``` ### 块级语句 ```svelte $: { total = 0; for (const item of items) total += item.value; } ``` ## Critical: export let Legacy Mode 中用 `export let` 声明 props: ```svelte <script> export let name; // 必需 prop export let age = 18; // 带默认值 export let items = []; // 数组默认值 </script> ``` > Svelte 5 Runes:`let { name, age = 18 } = $props()` ### 重新导出(API) ```svelte <script> export function greet(name) { alert(`Hello ${name}!`); } export const VERSION = '1.0'; </script> ``` 父组件通过 `bind:this` 调用: ```svelte <script> let greeter; </script> <Greeter bind:this={greeter} /> <button on:click={() => greeter.greet('world')}>greet</button> ``` ### prop 重命名 ```svelte <script> export { foo as bar }; // 对外叫 bar,内部叫 foo </script> ``` ## Critical: $$props / $$restProps ### $$props(获取所有传入 props) ```svelte <script> let { foo, ...rest } = $$props; // foo 是显式 prop,rest 是其余所有 props </script> ``` > Svelte 5 Runes:`let { foo, ...rest } = $props()` ### $$restProps(仅剩余 props) ```svelte <script> export let required; let { ...rest } = $$props; </script> <!-- required 不在 rest 中 --> ``` ## Critical: createEventDispatcher Legacy 的事件分发机制(已被 Svelte 5 callback props 取代): ```svelte <script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); function handleClick() { dispatch('change', { value: 42 }); dispatch('complete'); // 无数据 } </script> <button on:click={handleClick}>发送</button> ``` ### 使用事件 ```svelte <Component on:change={(e) => console.log(e.detail)} /> ``` ### 类型化(TypeScript) ```svelte <script lang="ts"> const dispatch = createEventDispatcher<{ change: { value: number }; complete: null; }>(); </script> ``` > **Svelte 5 推荐**:直接用 callback props: > `<Component onChange={(detail) => handle(detail)} />` ## Critical: Slots `<slot>` 是 Legacy 的内容传递机制(Svelte 5 用 Snippets 替代): ### 默认 slot ```svelte <!-- Component.svelte --> <div class="card"> <slot /> </div> <!-- 使用 --> <Component> <p>内容</p> </Component> ``` ### 命名 slot ```svelte <!-- Component.svelte --> <slot name="footer" /> <slot name="header" /> <!-- 使用 --> <Component> <p slot="header">头部</p> <p slot="footer">尾部</p> </Component> ``` ### Slot props(向 slot 传数据) ```svelte <!-- Component.svelte --> <slot value={count} onClick={handleClick} /> <!-- 使用 --> <Component let:value let:onClick> <p>{value}</p> <button on:click={onClick}>click</button> </Component> ``` > **注意**:Svelte 5 中,default slot props 需要 `let:` 前缀;named slots 的 slot props 不暴露给 named slots。 ### $$slots(检查 slot 是否存在) ```svelte <script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); $: if (!$$slots.footer) { // footer slot 未被提供 } </script> ``` ## Critical: svelte:component / svelte:self ### `<svelte:component>`(动态组件) ```svelte <script> let Current = FirstComponent; $: Current = showSecond ? SecondComponent : FirstComponent; </script> <svelte:component this={Current} /> ``` > Svelte 5 推荐:`<svelte:element this={Current} />` ### `<svelte:self>`(递归组件) ```svelte <script> import { svelte:self } from 'svelte'; </script> <svelte:self /> ``` ## Critical: svelte:fragment ```svelte <!-- Component.svelte --> <slot name="title" /> <div> <slot name="body" /> </div> <!-- 使用 --> <Component> <h1 slot="title">Title</h1> <svelte:fragment slot="body"> <p>多元素</p> <p>不会被包裹</p> </svelte:fragment> </Component> ``` ## Critical: v5 Migration Quick Reference | Legacy (Svelte 4) | Modern (Svelte 5) | |---------------------|----------------------| | `let count = 0`(顶层响应式) | `let count = $state(0)` | | `$: x = expr` | `let x = $derived(expr)` | | `$: { if (cond) x = v }` | `$effect(() => { if (cond) x = v })` | | `export let prop` | `let { prop } = $props()` | | `$$props` | `let { ...rest } = $props()` | | `<slot />` | `{@render children()}` | | `createEventDispatcher` | callback props | | `on:click={fn}` | `onclick={fn}` | | `<svelte:component this={x}>` | `<svelte:element this={x}>` | | `<svelte:self>` | `import Self from './This.svelte'` + `<Self>` | | `class:cool={isCool}` | `class={{ cool: isCool }}` | | `let:slotProp={value}` | Snippets 自动传递 | ## Gotchas 1. **Legacy `$:` 基于赋值** — 数组 `.push()` 等方法不触发更新 2. **Slot props 行为不同** — default slot 可访问 slot props,named slots 不可以 3. **`createEventDispatcher` 已废弃** — Svelte 5 不推荐,新代码用 callback props 4. **`$$slots` 是编译时注入** — 可在 script 中直接使用 `$:` 中引用 5. **`<svelte:self>` 需要导入** — `import { svelte:self } from 'svelte'` ## Critical: Svelte 4 Migration (Svelte 3 → Svelte 4) 如果你正在维护 Svelte 3 项目并升级到 Svelte 4,下面这些破坏性变更必须逐项核对。详细对照与自动化脚本见 `examples/migration-v4.md` 与 `references/migration-v4-reference.md`,源码基线在 `/tmp/svelte-llms.txt:6182`。 > **推荐起点**:`npx svelte-migrate@latest svelte-4` —— 脚本会自动处理多数条目;其余需要手动介入。 ### 最低版本要求 ```jsonc { "engines": { "node": ">=16" }, "devDependencies": { "svelte": "^4.0.0", "@sveltejs/kit": ">=1.20.4", "vite-plugin-svelte": ">=2.4.1", "svelte-loader": ">=3.1.8", "rollup-plugin-svelte": ">=7.1.5", "typescript": ">=5" } } ``` ### 主要破坏性变更速查 | 类别 | Svelte 3 | Svelte 4 | |------|----------|----------| | **Bundler browser condition** | 可选 | Rollup `browser: true` / Webpack `conditionNames: ['browser']` | | **CJS 输出** | 支持 | 移除(编译器、`svelte/register`、runtime) | | **`createEventDispatcher` 类型** | 可选 payload | 严格:`T \| undefined` 可选;`T` 必填;`null` 禁 detail | | **`Action` / `ActionReturn`** | params 隐式 `any` | 必须显式 `Action<HTMLElement, T>` | | **`onMount` 异步清理** | 不报错 | 返回 Promise 的清理函数会被忽略(TS 报错) | | **Custom Element** | `<svelte:options tag="x" />` | `<svelte:options customElement="x" />`(字符串或对象) | | **`SvelteComponentTyped`** | 与 `SvelteComponent` 并存 | 弃用,统一为 `SvelteComponent` | | **Transitions 默认范围** | 任意祖先块触发 | 仅直接父块触发,加 `\|global` 恢复旧行为 | | **Default slot bindings** | named slot 也可见 | 仅 default slot 可见 | | **Preprocessor 顺序** | markup×N, script×N, style×N | markup, script, style ×N(每个 preprocessor 内部三段) | | **`eslint-plugin-svelte3`** | 推荐 | 弃用,改 `eslint-plugin-svelte` | | **`inert` on outroing** | 不应用 | 默认应用(无障碍改进) | | **`classList.toggle`** | 兼容老浏览器 | 需要 polyfill | | **`CustomEvent`** | 兼容老浏览器 | 需要 polyfill | | **`derived` falsy 值** | 警告 | 抛错 | | **`svelte/internal` 类型** | 暴露 | 已移除 | | **`svelte.JSX` 命名空间** | 用 | 改 `svelteHTML` / `svelte/elements` | | **库作者 `peerDependencies`** | `^3` | `^3 \|\| ^4` | ### 自动化脚本能处理的
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기