Svelte 框架学习与开发文档

Svelte 框架学习与开发文档

1. 什么是 Svelte?

Svelte 是一个前端编译器,与 React、Vue 等框架不同,它在构建时将组件转换为高效的原生 JavaScript 代码,而不是在运行时进行虚拟 DOM diffing。这使得 Svelte 应用通常具有更小的体积和更好的性能。

2. 环境搭建

2.1 安装 Node.js

Svelte 开发需要 Node.js (v14.0.0 或更高版本),可以从 Node.js 官网 下载安装。

2.2 创建 Svelte 项目

使用官方模板创建新项目:

# 创建 Svelte 项目
npx degit sveltejs/template my-svelte-project

# 进入项目目录
cd my-svelte-project

# 安装依赖
npm install

# 启动开发服务器
npm run dev

对于 SvelteKit (全栈框架):

npm create svelte@latest my-sveltekit-project
cd my-sveltekit-project
npm install
npm run dev

3. 基础语法

3.1 组件结构

Svelte 组件使用 .svelte 扩展名,一个组件通常包含三个部分:

<!-- 样式 -->
<style>
  .title {
    color: blue;
  }
</style>

<!-- 标记/模板 -->
<h1 class="title">{message}</h1>

<!-- 脚本 -->
<script>
  let message = "Hello, Svelte!";
</script>

3.2 变量与插值

在模板中使用 { } 插入变量:

<script>
  let name = "World";
  let count = 10;
</script>

<h1>Hello {name}!</h1>
<p>Count: {count}</p>
<p>Double: {count * 2}</p>
<p>Upper case: {name.toUpperCase()}</p>

3.3 条件渲染

使用 {#if}{:else if}{:else} 进行条件渲染:

<script>
  let loggedIn = false;
  let userRole = "guest";
</script>

{#if loggedIn}
  <p>Welcome back!</p>
  {:else if userRole === "guest"}
  <p>Please log in</p>
  {:else}
  <p>Access denied</p>
{/if}

3.4 列表渲染

使用 {#each} 渲染列表:

<script>
  let items = ["Apple", "Banana", "Cherry"];
</script>

<ul>
  {#each items as item}
    <li>{item}</li>
  {/each}
</ul>

<!-- 带索引 -->
<ul>
  {#each items as item, index}
    <li>{index + 1}: {item}</li>
  {/each}
</ul>

<!-- 带key -->
<ul>
  {#each items as item (item)}
    <li>{item}</li>
  {/each}
</ul>

3.5 事件处理

使用 on: 指令监听事件:

<script>
  let count = 0;
  
  function increment() {
    count += 1;
  }
  
  function decrement() {
    count -= 1;
  }
  
  function reset() {
    count = 0;
  }
</script>

<button on:click={increment}>+</button>
<span>{count}</span>
<button on:click={decrement}>-</button>
<button on:click={reset}>Reset</button>

<!-- 内联事件处理 -->
<button on:click={() => count += 1}>+</button>

<!-- 事件修饰符 -->
<form on:submit|preventDefault={handleSubmit}>
  <!-- 表单内容 -->
</form>

常用事件修饰符:

  • preventDefault - 调用 event.preventDefault()
  • stopPropagation - 调用 event.stopPropagation()
  • passive - 优化触摸/滚轮事件性能
  • once - 事件只触发一次

3.6 绑定

使用 bind: 指令进行双向绑定:

<script>
  let name = "";
  let checked = false;
  let selected = "";
</script>

<!-- 文本输入 -->
<input type="text" bind:value={name} />
<p>Hello {name}!</p>

<!-- 复选框 -->
<input type="checkbox" bind:checked={checked} />
<p>Checked: {checked}</p>

<!-- 下拉菜单 -->
<select bind:value={selected}>
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="cherry">Cherry</option>
</select>
<p>Selected: {selected}</p>

<!-- 内容绑定 -->
<textarea bind:value={text} />

4. 组件通信

4.1 父组件向子组件传递数据

使用 props 传递数据:

<!-- Child.svelte -->
<script>
  export let name;
  export let age = 18; // 默认值
</script>

<p>{name} is {age} years old</p>
<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
</script>

<Child name="Alice" age={30} />

4.2 子组件向父组件传递数据

使用事件派发:

<!-- Child.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  
  const dispatch = createEventDispatcher();
  
  function handleClick() {
    dispatch('message', { text: 'Hello from child' });
  }
</script>

<button on:click={handleClick}>Send Message</button>
<!-- Parent.svelte -->
<script>
  import Child from './Child.svelte';
  
  function handleMessage(event) {
    console.log(event.detail.text); // 输出 "Hello from child"
  }
</script>

<Child on:message={handleMessage} />

4.3 跨组件通信

对于深层嵌套的组件,可以使用 context API:

<!-- 祖先组件 -->
<script>
  import { setContext } from 'svelte';
  
  const user = {
    name: 'Alice',
    age: 30
  };
  
  setContext('user', user);
</script>
<!-- 深层子组件 -->
<script>
  import { getContext } from 'svelte';
  
  const user = getContext('user');
</script>

<p>{user.name} is {user.age} years old</p>

5. 响应性 (Reactivity)

Svelte 的响应性基于赋值操作:

<script>
  let count = 0;
  
  function increment() {
    count += 1; // 触发更新
  }
  
  let user = { name: 'Alice' };
  
  function changeName() {
    user.name = 'Bob'; // 不会触发更新!
  }
  
  function correctChangeName() {
    user.name = 'Bob';
    user = user; // 触发更新
    // 或者
    user = { ...user, name: 'Bob' };
  }
  
  let items = ['a', 'b', 'c'];
  
  function addItem() {
    items.push('d'); // 不会触发更新!
  }
  
  function correctAddItem() {
    items.push('d');
    items = items; // 触发更新
    // 或者
    items = [...items, 'd'];
  }
</script>

使用 $: 创建反应式声明:

<script>
  let a = 1;
  let b = 2;
  
  $: sum = a + b; // 当 a 或 b 变化时自动更新
  
  $: {
    console.log(`a = ${a}, b = ${b}`);
    console.log(`sum = ${a + b}`);
  }
  
  $: if (a > 10) {
    alert('a is greater than 10');
  }
</script>

<input type="number" bind:value={a} />
<input type="number" bind:value={b} />
<p>Sum: {sum}</p>

6. 生命周期

Svelte 提供了四个生命周期函数:

<script>
  import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte';
  
  // 组件挂载后调用
  onMount(() => {
    console.log('Component mounted');
    
    // 清理函数
    return () => {
      console.log('Cleanup before unmount');
    };
  });
  
  // 组件销毁前调用
  onDestroy(() => {
    console.log('Component destroyed');
  });
  
  // 组件更新前调用
  beforeUpdate(() => {
    console.log('Before update');
  });
  
  // 组件更新后调用
  afterUpdate(() => {
    console.log('After update');
  });
</script>

7. 动画与过渡

Svelte 内置了动画和过渡效果:

<script>
  import { fade, fly, slide } from 'svelte/transition';
  import { cubicOut } from 'svelte/easing';
  let visible = true;
</script>

<button on:click={() => visible = !visible}>
  Toggle
</button>

{#if visible}
  <p transition:fade>
    Fade transition
  </p>
  
  <p transition:fly={{ y: 200, duration: 1000, easing: cubicOut }}>
    Fly transition
  </p>
  
  <p transition:slide>
    Slide transition
  </p>
{/if}

8. 状态管理

对于复杂应用,需要状态管理:

8.1 使用 stores

<!-- stores.js -->
import { writable, readable, derived } from 'svelte/store';

// 可写 store
export const count = writable(0);

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

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

使用 store:

<script>
  import { count, time, doubled } from './stores.js';
  
  function increment() {
    count.update(n => n + 1);
  }
  
  // 也可以直接设置值
  function reset() {
    count.set(0);
  }
</script>

<p>Count: {$count}</p>
<p>Doubled: {$doubled}</p>
<p>Time: {$time.toLocaleTimeString()}</p>
<button on:click={increment}>+</button>
<button on:click={reset}>Reset</button>

9. SvelteKit 简介

SvelteKit 是基于 Svelte 的全栈框架,提供:

  • 服务端渲染 (SSR)
  • 静态站点生成 (SSG)
  • 路由系统
  • API 路由
  • 代码分割
  • 离线支持

9.1 路由

SvelteKit 使用文件系统路由:

src/routes/
  index.svelte        # 首页
  about.svelte        # /about
  blog/
    index.svelte      # /blog
    [slug].svelte     # /blog/:slug (动态路由)
  api/
    users.js          # /api/users (API 路由)

9.2 加载数据

使用 load 函数在组件渲染前加载数据:

<!-- src/routes/blog/[slug].svelte -->
<script context="module">
  export async function load({ params, fetch }) {
    const res = await fetch(`https://api.example.com/posts/${params.slug}`);
    const post = await res.json();
    
    if (res.ok) {
      return {
        props: { post }
      };
    }
    
    return {
      status: res.status,
      error: new Error(`Could not load ${params.slug}`)
    };
  }
</script>

<script>
  export let post;
</script>

<h1>{post.title}</h1>
<div>{@html post.content}</div>

10. 构建与部署

10.1 构建应用

# 构建 Svelte 应用
npm run build

# 构建 SvelteKit 应用 (默认适配器)
npm run build

# 对于静态站点
npm run build -- --adapter static

10.2 部署选项

  • Vercel
  • Netlify
  • GitHub Pages
  • Cloudflare Pages
  • 自托管服务器

11. 常用资源

总结

Svelte 提供了一种简洁高效的前端开发方式,通过编译时转换而非运行时处理,实现了出色的性能表现。其响应式系统直观易用,组件模型简洁明了,是构建现代 Web 应用的优秀选择。

随着 SvelteKit 的成熟,Svelte 生态系统也日益完善,能够满足从简单交互组件到复杂全栈应用的各种开发需求。

要深入学习 Svelte,建议结合官方文档和实际项目练习,逐步掌握其核心概念和高级特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何之柱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值