Skip to main content

svelte-template-syntax

Svelte 5 模板语法技能。当用户需要使用 {#if}/{#each}/{#await}/{#snippet} 等块级语法、{@render}/@{html} 等模板标签、bind:、use:/transition:/in:/out:/animate:、style:/class/class:、{@attach} 等指令,或理解属性、事件、文本表达式等基础模板语法时使用。

Ir para a instalação

Informações da origem

Repositório
full-stack-skills/svelte-skills
Última atividade na origem
11 de setembro de 2026 às 13:43
Idioma detectado do SKILL.md
chinês
Estrelas
3
Forks
2

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
27 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
svelte-template-syntax
license
Apache-2.0
description
Svelte 5 模板语法技能。当用户需要使用 {#if}/{#each}/{#await}/{#snippet} 等块级语法、{@render}/@{html} 等模板标签、bind:、use:/transition:/in:/out:/animate:、style:/class/class:、{@attach} 等指令,或理解属性、事件、文本表达式等基础模板语法时使用。
# Svelte Template Syntax Reference (Svelte 5) 本技能覆盖 Svelte 5 模板语法,包括基础标记、块级表达式、模板标签、事件处理、属性绑定、style/class 指令、附件/动作、过渡和动画。 ## When to use this skill 当用户需要编写或理解 Svelte 组件中的模板语法,包括条件渲染、列表渲染、异步处理、片段复用、事件绑定、双向数据绑定、过渡动画等场景时使用本技能。 ## Critical: Basic Markup ### 元素标签 - 小写标签(`<div>`)= HTML 元素 - 大写/点号标签(`<Widget>`、`<my.stuff>`)= 组件 ### 属性绑定 ```svelte <!-- 布尔属性 --> <button disabled={!clickable}>...</button> <input required={false} /> <!-- 简写(同名字相同) --> <button {disabled}>...</button> <!-- 展开属性(顺序决定优先级:后写覆盖先写) --> <Widget {...props} a="b" /> <!-- 布尔属性:truthy 包含,falsy 排除 --> <div data-active={isActive}> <!-- true → 包含,false/null/undefined → 排除 --> ``` ### 事件处理 ```svelte <!-- onclick 是属性,不是指令 --> <button onclick={() => count++}>+</button> <input {onkeydown} /> <!-- 简写形式 --> <button {...handlerProps}> <!-- 展开形式 --> <!-- 事件委托:大多数事件委托到根节点,无需 stopPropagation --> <!-- 若需阻止:使用 svelte/events 的 on 函数 --> ``` ### 文本表达式 ```svelte <p>{expression}</p> <!-- null/undefined → 省略,其余转字符串 --> <p>Hello {name}!</p> <!-- 原始 HTML(注意 XSS) --> {@html rawContent} <!-- 转义花括号 --> <p>使用 &lbrace; 和 &rbrace;</p> ``` ## Critical: {#if ...} 条件渲染: ```svelte {#if count > 10} <p>big</p> {:else if count > 5} <p>medium</p> {:else} <p>small</p> {/if} ``` `{:else if}` 可以链式多次,`{:else}` 为最终 fallback。 ## Critical: {#each ...} 列表渲染: ```svelte {#each items as item} <li>{item.name}</li> {/each} <!-- 带索引 --> {#each items as item, i} <li>{i + 1}: {item.name}</li> {/each} <!-- 空列表 fallback --> {#each todos as todo} <p>{todo.text}</p> {:else} <p>No tasks!</p> {/each} ``` ### 带 key 的高效更新 ```svelte {#each items as item (item.id)} <li>{item.name}</li> {/each} ``` Key 必须是唯一标识(字符串/数字),用于 Svelte 高效 diff 和更新 DOM(插入/移动/删除而非整体重渲染)。 ### 解构和 rest ```svelte {#each items as { id, name, ...rest }} <li><span>{id}</span><MyComponent {...rest} /></li> {/each} {#each items as [id, ...values]} <li><span>{id}</span></li> {/each} ``` ### 渲染 N 次 ```svelte {#each { length: 8 }, rank} <div class:black={(rank) % 2 === 1}></div> {/each} ``` ## Critical: {#key ...} 当表达式变化时销毁并重建内容(触发过渡动画): ```svelte {#key value} <div transition:fade>{value}</div> {/key} ``` ## Critical: {#await ...} Promise 异步状态分支: ```svelte {#await promise} <p>loading...</p> {:then value} <p>result: {value}</p> {:catch error} <p>error: {error.message}</p> {/await} <!-- 简洁形式(无 pending UI) --> {#await promise then value} <p>{value}</p> {/await} <!-- 仅错误处理 --> {#await promise catch error} <p>{error.message}</p> {/await} ``` ### 懒加载组件 ```svelte {#await import('./Heavy.svelte') then { default: Component }} <Component /> {/await} ``` ### await 表达式(Svelte 5.36+ experimental) ```svelte <!-- 需 svelte.config.js 中启用 experimental.async --> <svelte:boundary> <p>{await fetchData()}</p> {#snippet pending()}<p>loading</p>{/snippet} </svelte:boundary> ``` 特性:同步更新、并发执行(独立 `await`)、`<svelte:boundary>` pending snippet、`fork()` API。 ## Critical: {#snippet ...} 可复用的标记片段,取代 Svelte 4 的 Slots: ```svelte {#snippet card(item)} <div class="card"> <h3>{item.title}</h3> <p>{item.body}</p> </div> {/snippet} {@render card(item)} ``` ### Snippet 作用域 Snippet 可以引用外部变量(script 变量或 `{#each}` 块级变量),并对**同一词法作用域**的兄弟/子节点可见: ```svelte {#each items as item} {#snippet itemCard()} <div>{item.name}</div> <!-- 引用 item --> {/snippet} {@render itemCard()} {/each} ``` ### 显式 vs 隐式 prop ```svelte <!-- 隐式 prop(推荐)--> <Table {data}> {#snippet header()} <th>Name</th> {/snippet} </Table> <!-- 显式 prop --> <Table {data} header={myHeader} /> ``` ### 隐式 children 组件标签内的非 snippet 内容自动成为 `children` snippet: ```svelte <Button>click me</Button> <!-- Button.svelte --> <script> let { children } = $props(); </script> <button>{@render children()}</button> ``` ### 可选 snippet ```svelte {@render children?.()} <!-- 可选链 --> {#if children}{:else}fallback{/if} <!-- #if fallback --> ``` ### Snippet 类型定义 ```svelte <script lang="ts"> import type { Snippet } from 'svelte'; let { row }: { row: Snippet<[Item]> } = $props(); </script> ``` ### 导出 snippet(5.5+) ```svelte <script module> export { mySnippet }; </script> {#snippet mySnippet()} <div>content</div> {/snippet} ``` ### 程序化创建(createRawSnippet) ```ts import { createRawSnippet } from 'svelte'; const greet = createRawSnippet<[string]>((name) => ({ render: () => `<p>Hello, ${name}!</p>` })); ``` ## Critical: {@render ...} 渲染 snippet: ```svelte {@render snippetName(args)} {@render children?.()} <!-- 可选链安全调用 --> {@render (cond ? a : b)()} <!-- 任意表达式 --> ``` ## Critical: {@html ...} 插入原始 HTML(**注意 XSS 风险**): ```svelte {@html rawHtml} ``` - `{expression}` 自动转义 HTML 实体 - `{@html expression}` 直接插入原始 HTML,需确保内容可信 - 必须是**完整独立** HTML(不能跨 `{@html}` 拼接标签) - 不受 scoped 样式影响 — 用 `:global` 包裹 ## Critical: {@attach ...} 元素挂载时运行的函数(Svelte 5.29+),取代 `use:` action: ```svelte <script> /** @type {import('svelte/attachments').Attachment} */ function tooltip(node) { const tip = createTip(node); return { destroy() { tip.destroy(); } }; } </script> <button {@attach tooltip()}>hover</button> ``` ### 带参数的 Attachment Factory ```svelte function tooltip(content) { return (node) => { const tip = createTip(node, { content }); return { destroy() { tip.destroy(); } }; }; } <button {@attach tooltip(content)}>hover</button> ``` ### 条件 Attachment ```svelte <div {@attach enabled && myAttachment}>...</div> ``` ### 内联 Attachment ```svelte <canvas {@attach (canvas) => { const ctx = canvas.getContext('2d'); $effect(() => { ctx.fillStyle = color; /* ... */ }); }}></canvas> ``` ### 重新运行行为 `{@attach foo(bar)}` 在 `foo` 或 `bar` 变化时**完整重建**(与 action 不同)。 ### 从 Action 转换 ```js import { fromAction } from 'svelte/attachments'; const attach = fromAction(myAction); ``` ## Critical: bind: 指令 数据从子级回流到父级: ```svelte <!-- 简写 --> <input bind:value /> <input bind:value={value} /> ``` ### Function Bindings(5.9+) ```svelte <input bind:value={ () => value, (v) => value = v.toLowerCase() } /> ``` ### 完整 bind: 列表 | 指令 | 元素 | 类型 | |------|------|------| | `bind:value` | input/textarea/select | 双向 | | `bind:checked` | input[type=checkbox] | 双向 | | `bind:indeterminate` | input[type=checkbox] | 双向 | | `bind:group` | radio/checkbox 组 | 双向 | | `bind:files` | input[type=file] | 双向 | | `bind:open` | details | 双向 | | `bind:value` | select multiple | 数组 | | `bind:currentTime/paused/volume/muted/playbackRate` | audio/video | 双向 | | `bind:duration/buffered/seeking/ended/readyState/played` | audio/video | 只读 | | `bind:videoWidth/Height` | video | 只读 | | `bind:naturalWidth/Height` | img | 只读 | | `bind:innerHTML/innerText/textContent` | contenteditable | 双向 |
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub