Skip to main content

svelte-misc

Svelte 5 杂项技能。当用户需要了解 TypeScript 支持、自定义元素、浏览器兼容性、Svelte 4→5 迁移、FAQ 时使用。

Aller à l'installation

Informations de source

Dépôt
full-stack-skills/svelte-skills
Dernière activité de la source
11 septembre 2026 à 13:43
Langue détectée de SKILL.md
chinois
Étoiles
3
Forks
2

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
17 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
svelte-misc
license
Apache-2.0
description
Svelte 5 杂项技能。当用户需要了解 TypeScript 支持、自定义元素、浏览器兼容性、Svelte 4→5 迁移、FAQ 时使用。
# 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">` 启用类型注解;需要枚举 / 参数属性等运行时特性则需要预处理器。 ```svelte <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 + 透传 ```svelte <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` 属性接受与函数泛型同样的语法: ```svelte <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} ``` ### 包装组件(转发原生属性) ```svelte <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` ```ts class Counter { count = $state() as number; // 无初值类型会扩为 undefined constructor(initial: number) { this.count = initial; } increment() { this.count += 1; } } ``` ### 增强 `svelte/elements` ```ts /// 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 <svelte:options customElement="my-element" /> <script> let { name = 'world' } = $props(); </script> <h1>Hello {name}!</h1> <slot /> ``` 导入即自动 `customElements.define()` 注册。消费者可读写 DOM 属性: ```js const el = document.querySelector('my-element'); el.name = 'everybody'; // 触发 shadow DOM 更新 ``` > 必须显式声明 props(不能只写 `let props = $props()`),否则 Svelte 不知道要暴露哪些键。 ### `customElement` 选项 ```svelte <svelte:options customElement={{ tag: 'my-counter', shadow: 'open', props: { count: { type: 'Number', reflect: true, attribute: 'start' } }, extend: (Ctor) => class extends Ctor { /* ... */ } }} /> ``` | 字段 | 取值 | 默认 | 作用 | |------|------|------|------| | `tag` | string | — | 标签名;设置后自动注册 | | `shadow` | `'none' \| 'open' \| 'closed' \| ShadowRootInit` | `'open'` | Shadow root 配置 | | `props.<name>.attribute` | string | 小写 prop 名 | 自定义属性名 | | `props.<name>.reflect` | boolean | `false` | 将 prop 值镜像到 HTML 属性 | | `props.<name>.type` | `'String' \| 'Boolean' \| 'Number' \| 'Array' \| 'Object'` | `'String'` | 属性 ↔ prop 类型转换 | | `extend` | `(Ctor) => class` | — | 包装生成的类(可注入 lifecycle / ElementInternals)| ### `$host()` Rune + 生命周期 ```svelte <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 / Edge | 87 | | Firefox | 83 | | Safari | 14 | | Opera | 73 | | Opera (Android) | 62 | | Samsung Internet | 14.0 | | Android WebView | 87 | | Internet Explorer | **不支持** | ### 例外情况 | 功能 | Chrome/Edge | Firefox | Safari | |------|-------------|---------|--------| | `$state.snapshot` | 98 | 94 | 15.4 | | `bind:devicePixelContentBoxSize` | — | 93 | 不支持 | | `flip`(来自 `svelte/animate`) | — | 126 | — | ### SSR 浏览器 API 保护 ```svelte <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 开销: ```js let user = $state.raw<User | null>(null); ``` ### `$derived` > `$effect` 用于纯计算 ```js 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 当作会变化、事件用属性语法 ```js 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 ### 最小版本 | 依赖 | 要求 | |------|------| | Node | 16+ | | SvelteKit | 1.20.4+(如使用) | | `vite-plugin-svelte` | 2.4.1+ | | TypeScript | 5+ | ### 核心迁移对照 | Svelte 4 | Svelte 5 | |---------|---------| | `let x = 0`(顶层响应式) | `let x = $state(0)` | | `$: x = a + b` | `let x = $derived(a + b)` | | `$: { ... }` | `$effect(() => { ... })` | | `export let prop` | `let { prop } = $props()` | | `<slot />` | `{@render children()}` | | `createEventDispatcher` | callback props | | `on:click={fn}` | `onclick={fn}` | ### 自动迁移工具 ```bash 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()` | | `createEventDispatcher` | callback props / `$bindable` | | Slots | Snippets | | `on:event` | `onevent` | | `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?**
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub