视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
svelte【文档与办公】Svelte 5 with runes reactivity system. Covers components, state management, and reactive declarations. USE WHEN: user mentions "Svelte", "runes", "$state", "$derived", "$effect", "SvelteKit", asks about "Svelte 5 patterns", "reactive runes" DO NOT USE FOR: Svelte 4 and earlier - use Svelte 4 documentation, React - use `frontend-react`, Vue - use `v…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: svelte description: | Svelte 5 with runes reactivity system. Covers components, state management, and reactive declarations.
USE WHEN: user mentions "Svelte", "runes", "$state", "$derived", "$effect", "SvelteKit", asks about "Svelte 5 patterns", "reactive runes"
frontend-react, Vue - use vue-composition, Angular - use angular
allowed-tools: Read, Grep, Glob, Write, EditFull Reference: See advanced.md for WebSocket store patterns, room management, Socket.IO integration, and SvelteKit SSE patterns.
Deep Knowledge: Use
mcp__documentation__fetch_docswith technology:sveltefor comprehensive documentation.
Skip this skill when:
frontend-react)vue-composition)angular)<script lang="ts">
interface Props {
name: string;
count?: number;
}
let { name, count = 0 }: Props = $props();
let localState = $state('');
let doubled = $derived(count * 2);
function handleClick() {
localState = 'clicked';
}
</script>
<div>
<h1>Hello {name}</h1>
<p>Count: {count}, Doubled: {doubled}</p>
<button onclick={handleClick}>Click</button>
</div>
<style>
div { padding: 1rem; }
</style>
| Rune | Purpose |
|---|---|
$state | Reactive state |
$derived | Computed values |
$effect | Side effects |
$props | Component props |
$bindable | Two-way bindable props |
{#if}, {#each}, {#await} blocksbind: for two-way bindinguse: for actions (reusable behaviors)<!-- Svelte 4 -->
<script>
export let count = 0;
$: doubled = count * 2;
</script>
<!-- Svelte 5 -->
<script>
let { count = 0 } = $props();
let doubled = $derived(count * 2);
</script>
| Anti-Pattern | Why It's Bad | Correct Approach |
|---|---|---|
Using Svelte 4 $: syntax | Deprecated in Svelte 5 | Use $derived rune |
Not using $props() | Old prop syntax | Use let { prop } = $props() |
Using {@html} without sanitization | XSS vulnerability | Use DOMPurify before rendering |
| Complex logic in templates | Hard to read/test | Extract to $derived or functions |
Not cleaning up in onDestroy | Memory leaks | Clear timers, unsubscribe |
| Overusing stores | Unnecessary complexity | Use component state when possible |
| Issue | Likely Cause | Solution |
|---|---|---|
| State not reactive | Using regular let | Use $state() rune |
| Derived not updating | Not using $derived | Convert to $derived() |
| Effect running too often | Missing dependencies | Check $effect dependencies |
| Props not updating | Using old syntax | Use $props() rune |
| Memory leaks | No cleanup | Add onDestroy() lifecycle |
| Binding not working | Wrong syntax | Use bind:value not :value |
<script lang="ts">
import DOMPurify from 'dompurify';
let { rawHtml }: { rawHtml: string } = $props();
let safeHtml = $derived(DOMPurify.sanitize(rawHtml));
</script>
{@html safeHtml}
import { render, screen } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import Counter from './Counter.svelte';
describe('Counter', () => {
it('increments count on click', async () => {
const user = userEvent.setup();
render(Counter, { props: { initial: 0 } });
const button = screen.getByRole('button');
await user.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
});
| Metric | Target |
|---|---|
| Bundle size | < 50KB |
| First Contentful Paint | < 1s |
| Time to Interactive | < 2s |
| Hydration time | < 100ms |