mcpField
S
svelte-misc

svelte-misc

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

关于 svelte-misc

面向 Svelte 5 开发者的参考技能,汇集 TypeScript、自定义元素、浏览器支持、最佳实践与 Svelte 4 迁移资料,帮助处理开发和升级问题。

主要功能

  1. 01TypeScript 高级类型与组件模式
  2. 02自定义元素与生命周期参考
  3. 03浏览器兼容性与功能例外
  4. 04Svelte 5 响应式最佳实践
  5. 05Svelte 4 到 5 迁移指南

适用场景

  1. 01为泛型或包装组件添加类型
  2. 02构建 Web Components
  3. 03评估目标浏览器的功能支持
  4. 04逐步将 Svelte 4 项目迁移到 5

安装

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

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

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

包含的文件

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

agents/
openai.yaml
examples/
best-practices.md
browser-support.md
custom-elements.md
debug-html.md
dynamic-components.md
migration-v4.md
README.md
typescript-advanced.md
typescript.md
references/
best-practices.md
browser-support.md
custom-elements.md
dynamic-reference.md
README.md
typescript-advanced.md
typescript-reference.md

详细介绍

Svelte Misc Reference (Svelte 5)

本技能覆盖 Svelte 5 的 TypeScript 高级支持、自定义元素(Web Components)、浏览器兼容性矩阵、Svelte 4→5 迁移指南、官方最佳实践与常见问答。

When to use this skill

当用户需要 TypeScript 类型标注(泛型、包装组件、DOM 类型增强)、创建自定义 Web 组件并使用 $host() / $bindable / extend、查看浏览器兼容性矩阵与功能例外、从 Svelte 4 迁移到 Svelte 5,或遵循 Svelte 5 推荐的 $state / $derived / $effect 模式时使用本技能。


Critical: TypeScript 高级

Svelte 原生支持 TypeScript(Vite 项目无需配置)。用 <script lang="ts"> 启用类型注解;需要枚举 / 参数属性等运行时特性则需要预处理器。

<script lang="ts">
  let name: string = 'world';
  function greet(name: string) { alert(`Hello, ${name}!`); }
</script>
<button onclick={(e: Event) => greet((e.target as HTMLElement).innerText)}>
  {name}
</button>

lang="ts" 默认只支持「类型只消失」的特性(注解、接口、泛型)。运行时代码特性(enum、private foo = 1 形式的参数属性)需配置 vitePreprocess({ script: true })。

类型 Props + 透传
<script lang="ts">
  import type { Snippet } from 'svelte';
  interface Props {
    requiredProperty: number;
    optionalProperty?: boolean;
    snippetWithStringArgument: Snippet<[string]>;
    eventHandler: (arg: string) => void;
    [key: string]: unknown; // 配合 ...rest 透传其他属性
  }
  let { requiredProperty, optionalProperty, snippetWithStringArgument,
        eventHandler, ...rest }: Props = $props();
</script>
泛型组件

<script> 的 generics 属性接受与函数泛型同样的语法:

<script lang="ts" generics="Item extends { text: string }">
  interface Props { items: Item[]; select(item: Item): void; }
  let { items, select }: Props = $props();
</script>
{#each items as item}
  <button onclick={() => select(item)}>{item.text}</button>
{/each}
包装组件(转发原生属性)
<script lang="ts">
  import type { HTMLButtonAttributes } from 'svelte/elements';
  let { children, ...rest }: HTMLButtonAttributes = $props();
</script>
<button {...rest}>{@render children?.()}</button>

无专用接口的元素用 SvelteHTMLElements['div'] 形式。Component / ComponentProps<T> 用于约束动态组件与提取现有组件的 props。

类中 $state
class Counter {
  count = $state() as number; // 无初值类型会扩为 undefined
  constructor(initial: number) { this.count = initial; }
  increment() { this.count += 1; }
}
增强 svelte/elements
/// file: additional-svelte-typings.d.ts
declare module 'svelte/elements' {
  export interface SvelteHTMLElements { 'custom-button': HTMLButtonAttributes; }
  export interface HTMLAttributes<T> { globalattribute?: string; }
}
export {}; // 必须——否则会覆盖原模块

Critical: Custom Elements(Web Components)

基础用法
<svelte:options customElement="my-element" />
<script>
  let { name = 'world' } = $props();
</script>
<h1>Hello {name}!</h1>
<slot />

导入即自动 customElements.define() 注册。消费者可读写 DOM 属性:

const el = document.querySelector('my-element');
el.name = 'everybody'; // 触发 shadow DOM 更新

必须显式声明 props(不能只写 let props = $props()),否则 Svelte 不知道要暴露哪些键。

customElement 选项
<svelte:options customElement={{
  tag: 'my-counter',
  shadow: 'open',
  props: { count: { type: 'Number', reflect: true, attribute: 'start' } },
  extend: (Ctor) => class extends Ctor { /* ... */ }
}} />
字段取值默认作用
tagstring—标签名;设置后自动注册
shadow'none' | 'open' | 'closed' | ShadowRootInit'open'Shadow root 配置
props.<name>.attributestring小写 prop 名自定义属性名
props.<name>.reflectbooleanfalse将 prop 值镜像到 HTML 属性
props.<name>.type'String' | 'Boolean' | 'Number' | 'Array' | 'Object''String'属性 ↔ prop 类型转换
extend(Ctor) => class—包装生成的类(可注入 lifecycle / ElementInternals)
$host() Rune + 生命周期
<svelte:options customElement="tooltip" />
<script>
  import { $host } from 'svelte';
  let { text = 'hi' } = $props();
  function focus() { $host().focus(); }
</script>
<button onclick={focus}>{text}</button>
  • 内部组件在 connectedCallback 之后的下一个 tick 创建;插入前设置的属性被缓冲并应用。
  • Shadow DOM 更新批处理到下一个 tick;DOM 移动不会触发不必要的卸载。
  • disconnectedCallback 后下一个 tick 销毁。组件方法 mount 后才可用;要更早暴露请在 extend 类里声明。
重要注意事项
  • 样式封装而非「作用域」——全局 CSS 无法穿透 shadow root。
  • CSS 内联为 JS 字符串而非单独 .css 文件。
  • 不适合 SSR(shadow DOM 在 JS 加载前不可见)。
  • 插槽内容积极渲染(不像 Svelte 默认懒渲染),<slot> 在 {#each} 里不会复制内容。
  • let: 指令对自定义元素无效。Svelte context 不能跨自定义元素边界。
  • 不要命名 on* 属性(被解释为事件监听器)。

Critical: Browser Support

Svelte 5 目标是 Baseline 2020。

浏览器最低版本
Chrome / Edge87
Firefox83
Safari14
Opera73
Opera (Android)62
Samsung Internet14.0
Android WebView87
Internet Explorer不支持
例外情况
功能Chrome/EdgeFirefoxSafari
$state.snapshot989415.4
bind:devicePixelContentBoxSize—93不支持
flip(来自 svelte/animate)—126—
SSR 浏览器 API 保护
<script>
  import { onMount } from 'svelte';
  onMount(() => {
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  });
</script>

优先用 <svelte:window> / <svelte:document>;Svelte 自动处理 SSR 与卸载。


Critical: Best Practices

$state — 只在需要时声明

只把会触发更新($effect / $derived / 模板)的值声明为 $state。大型只重赋值对象(API 响应)用 $state.raw 避免 Proxy 开销:

let user = $state.raw<User | null>(null);
$derived > $effect 用于纯计算
let square = $derived(num * num); // 好
// let square; $effect(() => { square = num * num; }); // 差

复杂逻辑用 $derived.by(() => { ... })。Derived 可写;对象/数组结果不会被深层代理。

$effect 是 escape hatch

优先工具:同步外部库 → {@attach ...};响应用户输入 → 处理器;调试日志 → $inspect / $inspect.trace;观察外部源 → createSubscriber。永远不要 if (browser) { ... } 包 effect——effect 本就不在服务端运行。

Props 当作会变化、事件用属性语法
let { type } = $props();
let color = $derived(type === 'danger' ? 'red' : 'green');

<svelte:window> / <svelte:document> 用于全局监听;不要 onMount 手动绑。Snippets 替代 Slots,{#each ... (item.id)} 用稳定 key(不可用 index)。style:-- 把 JS 变量透到 CSS 自定义属性;用 CSS 变量(而非 :global)穿透子组件样式;用 createContext 替代模块级共享状态(提供类型安全 + 防止 SSR 用户间泄漏)。

新代码避免 Legacy

on:click → onclick;export let → $props();$: → $derived / $effect;<slot> → snippet;use:action → {@attach ...}。


Critical: Svelte 4 Migration Guide

最小版本
依赖要求
Node16+
SvelteKit1.20.4+(如使用)
vite-plugin-svelte2.4.1+
TypeScript5+
核心迁移对照
Svelte 4Svelte 5
let x = 0(顶层响应式)let x = $state(0)
$: x = a + blet x = $derived(a + b)
$: { ... }$effect(() => { ... })
export let proplet { prop } = $props()
<slot />{@render children()}
createEventDispatchercallback props
on:click={fn}onclick={fn}
自动迁移工具
npx svelte-migrate@latest svelte-5 my-project
重要行为变化
  • 转换默认 local(外层控制流不影响子 transition)。
  • 默认插槽绑定不会进入具名插槽。
  • 预处理器顺序:markup → script → style(按声明顺序逐个执行)。
  • createEventDispatcher 严格模式下检查可选 / 必传 / 无参类型(之后用 callback props 替代)。
  • Action / ActionReturn 默认参数类型为 undefined,需要参数时显式声明。
  • SvelteComponentTyped 已弃用,统一用 SvelteComponent。
  • CJS 输出与 svelte/register 被移除。
  • 删除 svelte.JSX,改用 svelteHTML / svelte/elements。
  • 打包器必须指定 browser 条件(SvelteKit / Vite 自动;Rollup 用 @rollup/plugin-node-resolve 设 browser: true;Webpack 在 conditionNames 加 "browser")。

Critical: Svelte 5 Migration Guide (Concept Summary)

Runes 系统:$state / $derived / $effect 替代隐式响应式;Snippets 替代 Slots;事件属性替代 on:;$effect 显式追踪依赖;$state 对对象/数组做深层 Proxy。

移除替代
let 顶层隐式响应式$state
$: 语句$derived / $effect
export let / $$props / $$restProps$props()
createEventDispatchercallback props / $bindable
SlotsSnippets
on:eventonevent
beforeUpdate / afterUpdate$effect.pre / $effect

新增:$state.eager、$effect.pre、$effect.tracking、$state.snapshot、hydratable、fork()、{#key} 过渡触发、<svelte:boundary>、createContext。


FAQ

Q: Svelte 和 Vue/React 的核心区别? A: Svelte 无虚拟 DOM——编译时生成精确 DOM 更新代码,运行时零框架开销。

Q: Svelte 5 和 Svelte 4 可以共存吗? A: 可以。Svelte 5 仍支持 Legacy Mode,Svelte 4 的 $: 与 export let 可继续用;可在同一项目渐进迁移。

Q: 如何升级到 Svelte 5? A: ① 升级 svelte + sveltekit / vite-plugin-svelte;② 跑 npx svelte-migrate@latest svelte-5;③ 逐步迁到 Runes Mode。

Q: Svelte 支持 SSR / TypeScript 吗? A: 都原生支持。SSR 用 render() 或 SvelteKit;TS 直接用 <script lang="ts">,CI 跑 svelte-check。

Q: Svelte 有虚拟 DOM 吗? A: 没有。Svelte 编译器生成精确 DOM 操作代码(element.textContent = ...),而非通过 vDOM diffing。

Q: 哪些浏览器支持 Svelte 5? A: Baseline 2020(Chrome / Edge 87+、Firefox 83+、Safari 14+)。不支持 IE;少数功能需更高版本(见上表)。

Q: 自定义元素的样式如何控制? A: 默认 shadow root 模式 'open',全局 CSS 不会穿透。可用 shadow: 'none' 继承全局样式;用 CSS 变量穿透 scoped 样式。


Quick Fixes

问题解决方案
Svelte 4 代码报错确认组件未使用 $state(进入 Runes Mode)
$: 不生效升级到 Svelte 5,Legacy Mode 仍支持
TypeScript 报错确认 <script lang="ts"> 和 TypeScript 5+
迁移后打包变大检查 tree-shaking 配置
属性以 on 开头被监听重命名避免 on* 前缀
自定义元素 SSR 没内容预渲染不支持 shadow DOM;等 JS 加载
generic component 类型报错检查 generics 字符串(与函数泛型同语法)

Gotchas

  1. Svelte 5 自动进入 Runes Mode — 只要使用了任何 Rune($state 等)即为 Runes Mode。
  2. Legacy Mode — 可通过 <svelte:options runes={false}> 强制启用。
  3. on:click 已废弃 — Legacy Mode 仍可用,但会警告。
  4. createEventDispatcher 已弃用 — 新代码用 callback props。
  5. $bindable(default) — 仅在父组件未传 prop 时作 fallback;父组件传 undefined 会保留 undefined。
  6. bind:this 泛型组件 — 实例类型为 Component<Props> | null,需要断言。
  7. 自定义元素 inline CSS — 没有可被外部样式表链接的 .css 文件。
  8. 服务端 effect 不运行 — 不要用 if (browser) 包 effect 主体。

示例

Svelte 5 功能的实用示例。

  • 动态组件:svelte:element 和 {#key} 块
  • 调试与 HTML:@html、@debug、@const
  • TypeScript:
    • TypeScript 基础 — 类型化属性、泛型、事件处理程序、组件引用
    • TypeScript 进阶 — 14 种模式:预处理器、泛型约束、包装组件、Component 类型、类中的 $state、svelte/elements 扩展、svelte-check、$bindable、表单状态
  • 自定义元素:自定义元素 — 12 种模式:customElement 选项、$host()、类型强制转换、反射、extend、ElementInternals、插槽语义
  • 最佳实践:Svelte 5 最佳实践 — 14 种模式:$state.raw、$derived.by、带键的 each 块、CSS 变量、createContext、异步 Svelte、旧版功能的替代方案
  • 迁移:Svelte 3→4 迁移 — 10 种模式:tag → customElement、更严格的类型、过渡作用域、预处理器顺序、移除 CJS
  • 浏览器支持:浏览器支持 — 7 种模式:功能检测、polyfill、打包器目标、SSR 防护、$state.snapshot 回退方案、固定 Playwright 版本

参考资料

深入的参考文档。

  • 动态组件:动态组件参考 — svelte:element、{#key}、{@html}、@debug、@const
  • TypeScript:
  • 自定义元素:自定义元素 — customElement 接口、$host() Rune、生命周期、注意事项、ElementInternals
  • 最佳实践:最佳实践 — $state / $derived / $effect、属性、事件、片段、each 块、CSS 变量、上下文、异步
  • 浏览器支持:浏览器支持 — 最低版本矩阵、功能例外、polyfill、SSR 安全性、打包器配置
Quick Links
FeatureReference
svelte:elementDynamic Components
{#key}Dynamic Components
{@html} / @debug / @constDynamic Components
TS basicsTypeScript Basics
TS advancedTypeScript Advanced
Generic componentsTypeScript Advanced
Wrapper componentsTypeScript Advanced
Component typeTypeScript Advanced
DOM augmentationTypeScript Advanced
customElement optionsCustom Elements
$host() runeCustom Elements
Web Component lifecycleCustom Elements
$state / $derived / $effect patternsBest Practices
Async SvelteBest Practices
Browser matrixBrowser Support
Feature exceptionsBrowser Support
PolyfillsBrowser Support

评论

支持 Markdown