搜索

PythonReactSEOPDF
GitHub Skill

svelte

Builds UIs with Svelte 5 including runes, components, reactivity, and stores. Use when creating Svelte applications, building reactive interfaces, or working with compile-time frameworks.

mgd34msu☆ 3 仓库 Stars0 仓库 Forks

安装与使用

请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。

查看来源 ↗使用指南

技能说明

Svelte 5

A framework that compiles components to efficient JavaScript at build time.

Quick Start

Create project:

npx sv create my-app
cd my-app
npm install
npm run dev

Component Basics

<script lang="ts">
  let count = $state(0);

  function increment() {
    count++;
  }
</script>

<button onclick={increment}>
  Count: {count}
</button>

<style>
  button {
    font-weight: bold;
  }
</style>

Runes (Svelte 5)

$state - Reactive State
<script lang="ts">
  // Primitive state
  let count = $state(0);
  let name = $state('');

  // Object state (deeply reactive)
  let user = $state({
    name: 'John',
    email: 'john@example.com',
  });

  // Array state
  let items = $state<string[]>([]);

  function addItem(item: string) {
    items.push(item); // Mutations work!
  }
</script>

<p>{count}</p>
<p>{user.name}</p>
$derived - Computed Values
<script lang="ts">
  let count = $state(0);
  let items = $state([1, 2, 3]);

  // Simple derived
  let doubled = $derived(count * 2);

  // Complex derived
  let total = $derived(items.reduce((a, b) => a + b, 0));

  // Derived with function
  let expensive = $derived.by(() => {
    // Complex computation
    return items.filter(x => x > count).length;
  });
</script>

<p>Count: {count}, Doubled: {doubled}</p>
$effect - Side Effects
<script lang="ts">
  let count = $state(0);

  // Runs when dependencies change
  $effect(() => {
    console.log(`Count is now ${count}`);
  });

  // With cleanup
  $effect(() => {
    const interval = setInterval(() => count++, 1000);

    return () => {
      clearInterval(interval);
    };
  });

  // Pre-effect (runs before DOM update)
  $effect.pre(() => {
    console.log('Before DOM update');
  });
</script>
$props - Component Props
<!-- Button.svelte -->
<script lang="ts">
  interface Props {
    variant?: 'primary' | 'secondary';
    disabled?: boolean;
    children: import('svelte').Snippet;
  }

  let { variant = 'primary', disabled = false, children }: Props = $props();
</script>

<button class={variant} {disabled}>
  {@render children()}
</button>
<!-- Usage -->
<Button variant="primary">
  Click me
</Button>
$bindable - Two-way Binding Props
<!-- Input.svelte -->
<script lang="ts">
  let { value = $bindable('') }: { value: string } = $props();
</script>

<input bind:value />
<!-- Usage -->
<script lang="ts">
  let name = $state('');
</script>

<Input bind:value={name} />

Events

DOM Events
<script lang="ts">
  function handleClick(event: MouseEvent) {
    console.log('Clicked', event.target);
  }

  function handleInput(event: Event) {
    const target = event.target as HTMLInputElement;
    console.log(target.value);
  }
</script>

<button onclick={handleClick}>Click</button>
<input oninput={handleInput} />

<!-- Inline handlers -->
<button onclick={() => count++}>Increment</button>

<!-- Modifiers -->
<form onsubmit|preventDefault={handleSubmit}>
  <button>Submit</button>
</form>
Component Events (Callbacks)
<!-- Child.svelte -->
<script lang="ts">
  let { onchange }: { onchange: (value: string) => void } = $props();
</script>

<input oninput={(e) => onchange(e.target.value)} />
<!-- Parent.svelte -->
<script lang="ts">
  function handleChange(value: string) {
    console.log(value);
  }
</script>

<Child onchange={handleChange} />

Control Flow

Conditionals
{#if condition}
  <p>True</p>
{:else if otherCondition}
  <p>Other</p>
{:else}
  <p>False</p>
{/if}
Loops
{#each items as item, index (item.id)}
  <li>{index}: {item.name}</li>
{:else}
  <p>No items</p>
{/each}
Await
{#await promise}
  <p>Loading...</p>
{:then data}
  <p>{data}</p>
{:catch error}
  <p>Error: {error.message}</p>
{/await}

<!-- Short form -->
{#await promise then data}
  <p>{data}</p>
{/await}
Key Block
{#key value}
  <!-- Recreates component when value changes -->
  <Component />
{/key}

Snippets (Svelte 5)

<script lang="ts">
  let items = $state(['a', 'b', 'c']);
</script>

{#snippet listItem(item: string, index: number)}
  <li>{index}: {item}</li>
{/snippet}

<ul>
  {#each items as item, i}
    {@render listItem(item, i)}
  {/each}
</ul>
Passing Snippets as Props
<!-- List.svelte -->
<script lang="ts">
  import type { Snippet } from 'svelte';

  interface Props {
    items: string[];
    row: Snippet<[string, number]>;
  }

  let { items, row }: Props = $props();
</script>

<ul>
  {#each items as item, i}
    {@render row(item, i)}
  {/each}
</ul>
<!-- Usage -->
<List {items}>
  {#snippet row(item, index)}
    <li class="custom">{index}: {item}</li>
  {/snippet}
</List>

Bindings

Form Bindings
<script lang="ts">
  let text = $state('');
  let checked = $state(false);
  let selected = $state('');
  let group = $state<string[]>([]);
</script>

<input bind:value={text} />
<input type="checkbox" bind:checked />
<select bind:value={selected}>
  <option value="a">A</option>
  <option value="b">B</option>
</select>

<!-- Checkbox group -->
<input type="checkbox" bind:group value="one" />
<input type="checkbox" bind:group value="two" />

<!-- Radio group -->
<input type="radio" bind:group={selected} value="a" />
<input type="radio" bind:group={selected} value="b" />
Element Bindings
<script lang="ts">
  let div: HTMLDivElement;
  let width = $state(0);
  let height = $state(0);
</script>

<div bind:this={div} bind:clientWidth={width} bind:clientHeight={height}>
  {width} x {height}
</div>

Lifecycle

<script lang="ts">
  import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';

  onMount(() => {
    console.log('Mounted');

    return () => {
      console.log('Cleanup on unmount');
    };
  });

  onDestroy(() => {
    console.log('Destroyed');
  });

  beforeUpdate(() => {
    console.log('Before update');
  });

  afterUpdate(() => {
    console.log('After update');
  });
</script>

Stores

// stores/count.ts
import { writable, derived, readable } from 'svelte/store';

// Writable store
export const count = writable(0);

// Derived store
export const doubled = derived(count, ($count) => $count * 2);

// Readable store
export const time = readable(new Date(), (set) => {
  const interval = setInterval(() => set(new Date()), 1000);
  return () => clearInterval(interval);
});

// Custom store
function createCounter() {
  const { subscribe, set, update } = writable(0);

  return {
    subscribe,
    increment: () => update((n) => n + 1),
    decrement: () => update((n) => n - 1),
    reset: () => set(0),
  };
}

export const counter = createCounter();
<script lang="ts">
  import { count, doubled, counter } from './stores/count';
</script>

<!-- Auto-subscribe with $ prefix -->
<p>Count: {$count}</p>
<p>Doubled: {$doubled}</p>

<button onclick={() => $count++}>Increment</button>
<button onclick={counter.increment}>Counter++</button>

Context

<!-- Parent.svelte -->
<script lang="ts">
  import { setContext } from 'svelte';

  setContext('theme', {
    color: 'dark',
    toggle: () => { /* ... */ },
  });
</script>
<!-- Child.svelte -->
<script lang="ts">
  import { getContext } from 'svelte';

  interface ThemeContext {
    color: string;
    toggle: () => void;
  }

  const { color, toggle } = getContext<ThemeContext>('theme');
</script>

Actions

// actions/clickOutside.ts
export function clickOutside(node: HTMLElement, callback: () => void) {
  function handleClick(event: MouseEvent) {
    if (!node.contains(event.target as Node)) {
      callback();
    }
  }

  document.addEventListener('click', handleClick, true);

  return {
    destroy() {
      document.removeEventListener('click', handleClick, true);
    },
  };
}
<script lang="ts">
  import { clickOutside } from './actions/clickOutside';

  let open = $state(false);
</script>

{#if open}
  <div use:clickOutside={() => open = false}>
    Dropdown content
  </div>
{/if}

Transitions

<script lang="ts">
  import { fade, fly, slide, scale } from 'svelte/transition';
  import { quintOut } from 'svelte/easing';

  let visible = $state(true);
</script>

{#if visible}
  <div transition:fade={{ duration: 300 }}>
    Fades in and out
  </div>

  <div in:fly={{ y: 200 }} out:fade>
    Different in/out
  </div>

  <div transition:slide={{ duration: 500, easing: quintOut }}>
    Slides
  </div>
{/if}

Class and Style

<script lang="ts">
  let active = $state(false);
  let color = $state('red');
</script>

<!-- Class shortcuts -->
<div class:active>...</div>
<div class:active={isActive}>...</div>
<div class={active ? 'active' : ''}>...</div>

<!-- Style shortcuts -->
<div style:color>...</div>
<div style:color={color}>...</div>
<div style:--custom-property={value}>...</div>

Best Practices

  1. Use runes - $state, $derived, $effect for Svelte 5
  2. Extract logic - Use stores or modules for shared state
  3. Type props - Use TypeScript interfaces
  4. Use actions - Reusable DOM behaviors
  5. Prefer snippets - Over slots for typed templates

Common Mistakes

Mistake Fix
Using $: in Svelte 5 Use $derived or $effect
Forgetting $state Primitives need $state()
Wrong event syntax Use onclick not on:click (Svelte 5)
Store without $ Use $store for auto-subscribe
Missing key in each Add (item.id) for keyed each

Reference Files

使用示例

查看来源仓库中的使用示例与配置说明。

查看来源 ↗

来源历史

收录时间
2026-01-20
索引更新时间
2026-01-28
Branch
main

收录与同步日期属于本站记录。源码修改历史请查看来源仓库。

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!