Svelte
1. 概述
- Svelte 是一个前端框架,专注于编译时优化,区别于 React 和 Vue,它通过在编译时将组件转化为高效的 JavaScript 代码,消除了虚拟 DOM 的性能开销。
- 响应性:数据变化会直接影响视图,Svelte 利用编译时的静态分析自动处理组件的更新和重新渲染。
- 无框架运行时:Svelte 生成的代码没有框架运行时,这使得生成的应用体积小、性能高。
2. 基础概念
- Svelte 文件:每个组件是一个
.svelte
文件,包含三个部分:HTML、JavaScript、CSS。- HTML:组件的结构和模板。
- JavaScript:组件的逻辑和数据。
- CSS:样式表,支持局部样式。
- 组件:Svelte 的应用由多个组件组成,每个组件是独立的封装单元。组件间可以通过 props、events 和 store 进行交互。
- 编译过程:在开发时,Svelte 会将
.svelte
文件中的代码转化为高效的 JavaScript,减少运行时依赖,减少浏览器负担。
3. 响应式设计
响应式声明(Reactivity):Svelte 使用编译时的响应式语法,不需要手动管理依赖关系。通过
$:
来声明响应式变量,任何依赖该变量的地方会在其变化时自动更新。1
2let count = 0;
$: doubled = count * 2; // doubled 会自动更新响应式语法:你可以直接在模板中使用变量和计算值,它们会在相关数据变化时自动更新视图。
1
<p>{doubled}</p> // 当 count 改变时,doubled 会自动更新
赋值响应式:直接将某个值赋给另一个变量,也会触发响应式更新。
1
2let name = "Alice";
$: greeting = `Hello, ${name}!`;
4. 组件之间的数据传递
Props:通过
export
导出变量,使其成为组件的输入属性。子组件可以通过传递props
从父组件接收数据。1
2
3
4
5<script>
export let name;
</script>
<p>Hello, {name}!</p>父组件:
1
<Child name="Alice" />
事件:子组件可以通过
$emit
触发事件,父组件可以监听并响应这些事件。1
<button on:click={handleClick}>Click Me</button>
双向数据绑定:使用
bind:
语法来实现双向绑定,允许父组件和子组件之间同步数据。1
<input bind:value={name}>
Store:Svelte 提供了
store
来管理全局状态,writable
用于创建可变的状态,readable
用于只读状态。1
2import { writable } from 'svelte/store';
const count = writable(0);
5. 条件渲染和列表渲染
条件渲染:使用
{#if}
语法来进行条件渲染。1
2
3{#if count > 0}
<p>Count is greater than 0</p>
{/if}**条件渲染的
else
和elseif
**:可以配合else
和elseif
来处理多个条件分支。1
2
3
4
5
6
7{#if count > 0}
<p>Count is positive</p>
{:else if count < 0}
<p>Count is negative</p>
{:else}
<p>Count is zero</p>
{/if}列表渲染:使用
{#each}
来遍历数组并渲染。1
2
3{#each items as item}
<p>{item}</p>
{/each}列表渲染中的键值(Keyed each blocks):通过
key
为每个项目分配唯一标识符,以优化渲染性能。1
2
3{#each items as item (item.id)}
<p>{item.name}</p>
{/each}
6. 生命周期钩子
**
onMount
**:组件挂载时调用,类似于componentDidMount
(React)或mounted
(Vue)。1
2
3
4import { onMount } from 'svelte';
onMount(() => {
console.log('Component mounted');
});**
beforeUpdate
和afterUpdate
**:在组件更新前后调用,用于执行一些副作用。1
2
3import { beforeUpdate, afterUpdate } from 'svelte';
beforeUpdate(() => { console.log('Before update'); });
afterUpdate(() => { console.log('After update'); });**
onDestroy
**:在组件销毁时调用,类似于componentWillUnmount
(React)。1
2
3
4import { onDestroy } from 'svelte';
onDestroy(() => {
console.log('Component destroyed');
});
7. 样式和样式作用域
局部样式:Svelte 中的样式默认是局部的,仅作用于当前组件内的元素。
1
2
3<style>
p { color: red; }
</style>全局样式:如果需要全局样式,可以使用
:global
关键字。1
2
3
4
5<style>
:global(body) {
font-family: Arial, sans-serif;
}
</style>CSS 类绑定:使用
{className}
来动态添加类名。1
<button class:active={isActive}>Click Me</button>
8. 动画与过渡
过渡动画:Svelte 提供了内置的过渡效果,如
fade
、fly
、slide
等,可以直接应用在元素上。1
2
3<div transition:fade>
This will fade in/out
</div>自定义过渡:可以定义自己的过渡效果,利用
transition
导入不同的过渡动画函数。1
2import { fade, slide } from 'svelte/transition';
<div transition:fade>Content</div>动画:Svelte 也提供了动画支持,可以基于元素的状态或属性变化进行动画处理。
1
2import { fly } from 'svelte/transition';
<div transition:fly={{ x: 200 }}>Slide in</div>
9. 路由
没有内建路由功能:Svelte 不自带路由功能,但有第三方库如
svelte-routing
和svelte-navigator
来支持路由。1
pnpm add svelte-routing
**使用
svelte-routing
**:1
2
3
4
5
6
7
8
9
10
11
12<script>
import { Router, Route, Link } from 'svelte-routing';
</script>
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
</Router>
10. SvelteKit(用于 SSR 和 SSG)
SvelteKit 是 Svelte 官方推出的框架,提供了更高级的功能,包括服务器端渲染(SSR)、静态站点生成(SSG)和文件路由。
页面路由:SvelteKit 使用文件系统自动生成路由。每个
.svelte
文件都会变成一个页面。1
2
3src/routes/
└── index.svelte // 默认首页
└── about.svelte // About 页面
11. 工具和生态
- Svelte DevTools:浏览器扩展工具,帮助开发者调试 Svelte 应用。
- Svelte Preprocess:支持 TypeScript、SCSS、Less 等预处理器。
- 社区插件:Svelte 拥有很多社区插件,能够扩展其功能,如表单处理、路由、状态管理等。
12. 优缺点
- 优点:
- 编译时优化,生成高效的原生 JavaScript。
- 响应式设计简洁易懂,自动追踪数据变化。
- 生成的代码体积小,运行时无框架,性能极高。
- 缺点:
- 社区和生态系统较小,第三方库支持不如 React 和 Vue。
- 对大型项目的支持还不够成熟,缺乏一些成熟的开发工具。
总结
Svelte 是一个具有创新性的框架,尤其适合需要高性能和小体积的前端应用。它的响应式编程模式和无虚拟 DOM 的设计理念让开发者能够专注于业务逻辑,而不需要考虑性能优化。尽管生态系统不如 React 和 Vue 丰富,但 Svelte 的简洁性和高效性已吸引了越来越多的开发者。
基础项目结构
1 | my-svelte-app/ |
2. 目录和文件说明
public/
目录
index.html
: 默认的 HTML 模板,Svelte 会将生成的 JavaScript 和 CSS 文件插入到该模板中。favicon.ico
: 网站图标。global.css
: 全局样式表,通常包含一些通用的样式,例如字体、页面背景色等。- 其他资源: 比如
robots.txt
、manifest.json
等与前端资源有关的文件。
src/
目录
- **
assets/
**:存放静态资源(如图片、图标、字体文件等)。 components/
:所有的 Svelte 组件文件(.svelte 文件)。这些组件通常是独立的功能模块,包含了 HTML、CSS 和 JavaScript。- 例如:
Button.svelte
、Header.svelte
等。
- 例如:
routes/
:在使用 SvelteKit 时,这个目录存放页面组件,每个.svelte
文件对应一个路由。- 例如,
src/routes/index.svelte
是首页,src/routes/about.svelte
是关于页。 - 在 SvelteKit 中,路由是基于文件系统的,也就是说文件的路径直接对应于 URL 路径。
- 例如,
stores/
:存放全局状态管理的store
文件。- Svelte 的
store
用于在多个组件之间共享状态,可以使用writable
、readable
和derived
等类型的 store 来管理应用的状态。 - 例如:
src/stores/countStore.js
可能包含一个writable
store 来管理计数器状态。
- Svelte 的
- **
app.css
**:应用的基础样式。这里可以放置一些常见的样式设置,如全局布局、字体样式等。 - **
app.js
或main.js
**:应用的入口文件,通常会引入App.svelte
并进行挂载。
创建一个项目:
使用 create-svelte
工具创建项目
使用 pnpm
创建一个 Svelte 项目。执行以下命令:
1 | npx sv create my-svelte-app |
这条命令会创建一个新的 Svelte 项目,并将其命名为 my-svelte-app
(你可以根据需要修改项目名)。你可以选择模板类型,如 Skeleton project
、SvelteKit
等。
安装依赖
进入项目目录并安装依赖:
1 | cd my-svelte-app |
运行开发服务器
启动开发服务器:
1 | pnpm run dev |
持久化存储
在 Svelte 项目中,writable()
store 仅在 内存中存储,当页面刷新时会被 重置。
如果想要 刷新页面后仍然保留数据(比如 token
和 user
),就必须用 本地存储(localStorage) 来持久化。
🌟 1. localStorage
是什么?
localStorage
是浏览器提供的本地存储,数据不会因页面刷新而丢失,除非手动清除或代码删除。
📌 特点:
- 存储容量大(最多 5MB)。
- 不会随页面刷新而丢失。
- 只能存字符串(对象需要
JSON.stringify()
)。
📌 示例:
1 | localStorage.setItem("username", "张三"); // 存入 |
🌟 2. Svelte stores
的问题
Svelte 的 writable()
是内存存储:
1 | import { writable } from "svelte/store"; |
🔴 问题:用户登录后,刷新页面 user
变 null
,导致状态丢失。
🌟 3. 解决方案:封装 localStorage
持久化 stores
在 stores.js
里封装一个持久化的 Store,让它自动存入 localStorage
。
📍 路径:src/lib/stores.js
1 | import { writable } from "svelte/store"; |
📌 解释
初始值从
localStorage
读取,如果localStorage
里有用户数据,就用它,否则null
。创建
writable()
Store,用于存储用户信息。监听
store
变化:
- 如果
user
变了,自动存入localStorage
。 - **如果
user
设为null
**(用户退出),清除localStorage
。
- 如果
🌟 4. 登录时存储 user
📍 路径:src/routes/login/+page.svelte
1 | <script> |
📌 这里 user.set(res.data)
会自动存入 localStorage
!
- 刷新页面后
localStorage
仍然存在,所以user
不会丢失。
🌟 5. 退出登录时清除 localStorage
📍 路径:src/routes/profile/+page.svelte
1 | <script> |
📌 user.set(null)
会自动删除 localStorage
里的 user
数据!
- 这样就不会留存登录信息,确保用户 退出后必须重新登录。
🌟 6. API 请求时自动附带 token
在 axios
请求时,我们要**自动携带 token
**,所以要封装 API
请求拦截器。
📍 路径:src/lib/api.js
1 | import axios from "axios"; |
📌 重点
**请求时自动携带
token
**,从stores.js
读取user.token
并放入请求头。拦截 401 错误
,如果
token
失效:user.set(null)
清空用户信息。goto("/login")
跳转到登录页。
🌟 7. 页面刷新后仍然能保持登录
📍 路径:src/routes/home/+page.svelte
1 | <script> |
✅ 页面刷新后,userData
依然存在!
🌟 8. 总结
🔹 Svelte 默认 stores
不能持久化
- 刷新页面就会丢失数据。
🔹 解决方案
- 封装
stores.js
,用localStorage
读取 & 存储数据。 - **用户登录后,
user.set(res.data)
,会自动存入localStorage
**。 - **退出登录时
user.set(null)
,自动清空localStorage
**。 - 请求拦截器自动附带
token
,保证接口安全。 - 401 失效时,自动清除
user
并跳转到登录页。
💡 这样就实现了真正的持久化存储!即使刷新页面也不会丢失登录状态! 🚀
notyf
notyf
是一个轻量级、现代化的通知库,提供了简单易用的 API 来展示通知。它支持自定义样式、自动消失、位置设置等功能。
安装 notyf
首先,你需要安装 notyf
。如果你使用的是npm或yarn,可以通过以下命令安装:
1 | npm install notyf |
或者使用yarn
:
1 | yarn add notyf |
基本使用
1 | import { Notyf } from 'notyf'; |
配置选项
notyf
提供了许多配置选项来控制通知的显示方式。你可以在创建 Notyf
实例时传递一个配置对象来定制通知行为。
1 | const notyf = new Notyf({ |
自定义通知
你可以使用 open
方法来创建自定义通知。自定义通知支持传递多种类型的选项。
1 | // 自定义信息通知 |
显示不同类型的通知
notyf
支持显示几种不同类型的通知,主要有 success
, error
, 和 warning
类型。
1 | // 成功通知 |
完整示例
以下是一个在Svelte组件中使用 notyf
的完整示例:
1 | <script> |
总结
notyf
是一个简洁易用的通知库,适用于需要展示临时消息或通知的场景。它的API简单,能够快速集成进项目,并且提供了丰富的自定义选项,适应多种需求。
在 Svelte 中,获取当前路由的路径($route.path
)通常是通过路由库来实现的,像是 svelte-routing
或 @sveltejs/kit
(对于 SvelteKit)。如果你在使用 SvelteKit
,可以通过 $page
获取当前路径。
SvelteKit 中获取当前路径
在 SvelteKit 中,$page
是一个响应式的 store,它包含当前页面的信息,包括路径(path
)和查询参数等。
你可以通过 $page.url.pathname
来获取当前路径。
示例代码:
1 | <script> |
在 svelte-routing
中获取路径
如果你在使用 svelte-routing
,你可以通过 useLocation
钩子来获取当前路径。
示例代码:
1 | <script> |
总结:
- 在 SvelteKit 中,使用
$page.url.pathname
来获取当前路径。 - 在 svelte-routing 中,使用
useLocation
钩子来获取当前路径。