SvelteKit路由基础:构建你的第一个Svelte应用
1. 环境搭建
在开始构建第一个 SvelteKit 应用之前,确保你已经安装了 Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它为我们提供了在本地运行 SvelteKit 应用所需的环境。你可以从Node.js 官方网站下载并安装适合你操作系统的版本。
安装好 Node.js 后,我们使用 npm(Node Package Manager,它随 Node.js 一同安装)来创建一个新的 SvelteKit 项目。打开终端,运行以下命令:
npm create svelte@latest my - app
这里 my - app
是你项目的名称,你可以将其替换为你想要的任何名称。运行上述命令后,npm 会引导你完成项目初始化的一些配置步骤。例如,它会询问你是否要使用 TypeScript,是否要使用 ESLint 进行代码检查等等。你可以根据自己的需求进行选择。
完成配置后,进入项目目录:
cd my - app
然后安装项目所需的依赖:
npm install
至此,我们的 SvelteKit 项目环境搭建完成。
2. SvelteKit 路由基础概念
在 SvelteKit 中,路由是基于文件系统的。这意味着,你在项目的 src/routes
目录下创建的文件和目录结构,会直接映射到应用的路由。例如,如果你在 src/routes
目录下创建一个 about.svelte
文件,那么这个文件对应的路由就是 /about
。
2.1 页面路由
页面路由是 SvelteKit 中最基本的路由类型。每个 .svelte
文件在 src/routes
目录下都代表一个页面。例如,创建一个 home.svelte
文件:
<script>
let message = 'Welcome to my SvelteKit app!';
</script>
<main>
<h1>{message}</h1>
</main>
<style>
main {
padding: 20px;
}
</style>
当你启动应用(通过 npm run dev
命令)并访问根路径 /
时,默认会显示 home.svelte
的内容(前提是你没有其他优先级更高的路由匹配)。
2.2 动态路由
有时候我们需要处理动态的 URL 路径,比如显示不同用户的个人资料页面,每个用户有不同的 ID。在 SvelteKit 中,你可以通过在文件名中使用方括号来创建动态路由。例如,创建一个 src/routes/user/[id].svelte
文件:
<script context="module">
export async function load({ params }) {
const response = await fetch(`https://api.example.com/users/${params.id}`);
const user = await response.json();
return {
props: {
user
}
};
}
</script>
<script>
export let user;
</script>
<main>
<h1>{user.name}'s Profile</h1>
<p>{user.bio}</p>
</main>
<style>
main {
padding: 20px;
}
</style>
在这个例子中,[id]
是动态参数。load
函数是 SvelteKit 提供的一个特殊函数,用于在服务器端(或静态构建时)获取数据。params
对象包含了从 URL 中提取的动态参数,这里就是 id
。我们通过 fetch
从 API 获取用户数据,并将其作为 props
返回给组件。
当你访问 /user/123
这样的 URL 时,params.id
就会是 123
,组件会显示对应的用户资料。
2.3 嵌套路由
SvelteKit 支持嵌套路由,这在构建复杂的应用结构时非常有用。例如,假设你有一个博客应用,每个博客文章有评论。你可以创建如下的目录结构:
src/routes/blog/
├── [slug].svelte
└── comments/
└── index.svelte
[slug].svelte
文件可以显示博客文章的内容,而 comments/index.svelte
文件可以显示该文章的评论。访问 /blog/my - first - post
会显示博客文章,而访问 /blog/my - first - post/comments
会显示该文章的评论。
在 [slug].svelte
中,你可以使用 <svelte:component>
来渲染嵌套的组件:
<script>
import Comments from './comments/index.svelte';
</script>
<main>
<h1>Blog Post</h1>
<p>文章内容...</p>
<Comments />
</main>
<style>
main {
padding: 20px;
}
</style>
这样就实现了嵌套路由的基本功能。
3. 构建第一个 SvelteKit 应用 - 示例应用
我们来构建一个简单的图书管理应用,通过这个应用来深入了解 SvelteKit 的路由和其他特性。
3.1 项目结构初始化
在已经搭建好的 SvelteKit 项目基础上,我们先规划项目的路由结构。我们需要一个首页展示所有图书列表,一个添加图书的页面,以及一个图书详情页面。所以我们在 src/routes
目录下创建以下文件和目录:
src/routes/
├── books/
│ ├── [id].svelte
│ └── index.svelte
├── add - book.svelte
└── index.svelte
3.2 首页(index.svelte
)
首页将显示所有图书的列表。首先,我们创建一个简单的模拟图书数据。在 src/lib
目录下创建一个 books.js
文件:
export const books = [
{
id: 1,
title: 'JavaScript: The Definitive Guide',
author: 'David Flanagan'
},
{
id: 2,
title: 'Learning React',
author: 'Alex Banks and Eve Porcello'
}
];
然后在 src/routes/index.svelte
中:
<script context="module">
import { books } from '$lib/books.js';
export function load() {
return {
props: {
books
}
};
}
</script>
<script>
export let books;
</script>
<main>
<h1>Book List</h1>
<ul>
{#each books as book}
<li>
<a href={`/books/${book.id}`}>{book.title} by {book.author}</a>
</li>
{/each}
</ul>
<a href="/add - book">Add a new book</a>
</main>
<style>
main {
padding: 20px;
}
ul {
list - style - type: none;
padding: 0;
}
a {
text - decoration: none;
color: blue;
}
a:hover {
text - decoration: underline;
}
</style>
这里我们通过 load
函数将图书数据作为 props
传递给组件。然后使用 {#each}
指令遍历图书列表并显示,每个图书名称都链接到对应的图书详情页。同时还有一个链接指向添加图书的页面。
3.3 添加图书页面(add - book.svelte
)
添加图书页面允许用户输入图书的标题和作者,并提交保存。
<script>
let title = '';
let author = '';
const handleSubmit = (e) => {
e.preventDefault();
// 这里可以添加保存图书到后端的逻辑,暂时先打印数据
console.log({ title, author });
title = '';
author = '';
};
</script>
<main>
<h1>Add a Book</h1>
<form on:submit={handleSubmit}>
<label for="title">Title:</label>
<input type="text" bind:value={title} id="title" />
<br />
<label for="author">Author:</label>
<input type="text" bind:value={author} id="author" />
<br />
<button type="submit">Submit</button>
</form>
</main>
<style>
main {
padding: 20px;
}
form {
display: flex;
flex - direction: column;
}
label {
margin - top: 10px;
}
input {
margin - top: 5px;
}
button {
margin - top: 15px;
width: 100px;
}
</style>
在这个页面中,我们使用 bind:value
双向绑定输入框的值到 title
和 author
变量。当用户提交表单时,handleSubmit
函数被调用,目前只是在控制台打印数据,实际应用中可以将数据发送到后端服务器保存。
3.4 图书详情页面(books/[id].svelte
)
图书详情页面显示特定图书的详细信息。
<script context="module">
import { books } from '$lib/books.js';
export async function load({ params }) {
const book = books.find(b => b.id === parseInt(params.id));
return {
props: {
book
}
};
}
</script>
<script>
export let book;
</script>
<main>
{#if book}
<h1>{book.title}</h1>
<p>Author: {book.author}</p>
{:else}
<p>Book not found</p>
{/if}
</main>
<style>
main {
padding: 20px;
}
</style>
在 load
函数中,我们根据 URL 中的 id
参数从图书列表中找到对应的图书。如果找到,就将其作为 props
传递给组件并显示图书详情;如果没找到,则显示 “Book not found”。
3.5 启动应用
现在,我们可以通过 npm run dev
命令启动应用。在浏览器中访问 http://localhost:5173
,就可以看到我们构建的图书管理应用的首页,点击链接可以导航到图书详情页和添加图书页面,进行相应的操作。
4. 路由相关的高级功能
4.1 路由加载器(Loaders)的更多用法
路由加载器(load
函数)不仅可以用于获取数据,还可以进行一些预处理操作,比如验证用户权限。假设我们有一个管理页面,只有管理员用户可以访问。我们可以在 src/routes/admin/index.svelte
的 load
函数中进行权限验证:
<script context="module">
export async function load({ locals }) {
const isAdmin = locals.user && locals.user.role === 'admin';
if (!isAdmin) {
throw {
status: 403,
message: 'Forbidden'
};
}
return {
props: {}
};
}
</script>
<script>
// 组件逻辑
</script>
<main>
<h1>Admin Page</h1>
<p>This is the admin - only page.</p>
</main>
<style>
main {
padding: 20px;
}
</style>
这里我们假设 locals.user
是通过中间件或其他方式在请求上下文中设置的用户信息。如果用户不是管理员,就抛出一个带有 403
状态码的错误,SvelteKit 会自动返回相应的错误页面给用户。
4.2 路由过渡效果
SvelteKit 允许我们为路由切换添加过渡效果,提升用户体验。首先,在 src/routes/+layout.svelte
文件中(+layout.svelte
文件用于定义整个路由树的布局),我们可以设置过渡效果:
<script>
import { fade } from 'svelte/transition';
</script>
{#if $page}
<div transition:fade>
{#await $page.render()}
<p>Loading...</p>
{:then Component}
<svelte:component this={Component} {...$page.props} />
{:catch error}
<p>{error.message}</p>
{/await}
</div>
{/if}
在这个例子中,我们使用了 Svelte 内置的 fade
过渡效果。当路由切换时,页面内容会淡入淡出。$page
是 SvelteKit 提供的一个特殊变量,包含了当前页面的信息,$page.render()
用于渲染页面组件。
4.3 处理 404 页面
当用户访问一个不存在的路由时,我们需要提供一个友好的 404 页面。在 SvelteKit 中,我们可以在 src/routes/+error.svelte
文件中定义 404 页面的内容:
<script>
export let error;
</script>
<main>
{#if error.status === 404}
<h1>Page not found</h1>
<p>The page you are looking for does not exist.</p>
{:else}
<h1>An error occurred</h1>
<p>{error.message}</p>
{/if}
</main>
<style>
main {
padding: 20px;
}
</style>
这里根据 error
对象的 status
属性判断是否是 404 错误,如果是则显示相应的 404 提示信息,否则显示其他错误信息。
5. 与后端集成
在实际应用中,我们通常需要与后端服务器进行数据交互。SvelteKit 可以很方便地与各种后端技术集成。假设我们使用 Node.js 和 Express 搭建一个简单的后端 API 来处理图书管理应用的数据。
首先,创建一个新的目录 backend
并初始化一个新的 Node.js 项目:
mkdir backend
cd backend
npm init -y
然后安装 Express:
npm install express
创建一个 server.js
文件:
const express = require('express');
const app = express();
const books = [];
app.use(express.json());
// 获取所有图书
app.get('/books', (req, res) => {
res.json(books);
});
// 添加图书
app.post('/books', (req, res) => {
const newBook = req.body;
newBook.id = books.length + 1;
books.push(newBook);
res.json(newBook);
});
// 获取单个图书
app.get('/books/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (book) {
res.json(book);
} else {
res.status(404).json({ message: 'Book not found' });
}
});
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
在 SvelteKit 应用中,我们需要修改相应的路由组件来与后端 API 交互。例如,在 add - book.svelte
中,修改 handleSubmit
函数:
<script>
let title = '';
let author = '';
const handleSubmit = async (e) => {
e.preventDefault();
const newBook = { title, author };
try {
const response = await fetch('http://localhost:3000/books', {
method: 'POST',
headers: {
'Content - Type': 'application/json'
},
body: JSON.stringify(newBook)
});
if (response.ok) {
const data = await response.json();
console.log('Book added:', data);
title = '';
author = '';
} else {
console.error('Failed to add book');
}
} catch (error) {
console.error('Error adding book:', error);
}
};
</script>
<main>
<h1>Add a Book</h1>
<form on:submit={handleSubmit}>
<label for="title">Title:</label>
<input type="text" bind:value={title} id="title" />
<br />
<label for="author">Author:</label>
<input type="text" bind:value={author} id="author" />
<br />
<button type="submit">Submit</button>
</form>
</main>
<style>
main {
padding: 20px;
}
form {
display: flex;
flex - direction: column;
}
label {
margin - top: 10px;
}
input {
margin - top: 5px;
}
button {
margin - top: 15px;
width: 100px;
}
</style>
在 books/[id].svelte
和 index.svelte
中,也需要修改 load
函数来从后端 API 获取数据。例如,在 index.svelte
中:
<script context="module">
export async function load() {
try {
const response = await fetch('http://localhost:3000/books');
const books = await response.json();
return {
props: {
books
}
};
} catch (error) {
console.error('Error fetching books:', error);
return {
props: {
books: []
}
};
}
}
</script>
<script>
export let books;
</script>
<main>
<h1>Book List</h1>
<ul>
{#each books as book}
<li>
<a href={`/books/${book.id}`}>{book.title} by {book.author}</a>
</li>
{/each}
</ul>
<a href="/add - book">Add a new book</a>
</main>
<style>
main {
padding: 20px;
}
ul {
list - style - type: none;
padding: 0;
}
a {
text - decoration: none;
color: blue;
}
a:hover {
text - decoration: underline;
}
</style>
这样,我们的 SvelteKit 应用就可以与后端 API 进行数据交互,实现更完整的功能。
6. 部署 SvelteKit 应用
当我们完成了 SvelteKit 应用的开发后,就需要将其部署到服务器上供用户访问。
6.1 构建应用
首先,我们需要构建应用,将其转换为可以部署的静态文件。在项目根目录下运行以下命令:
npm run build
这会在项目根目录下生成一个 build
目录,里面包含了应用的所有静态文件。
6.2 部署到 Vercel
Vercel 是一个非常流行的前端应用部署平台,对 SvelteKit 有很好的支持。
首先,确保你已经安装了 Vercel CLI:
npm install -g vercel
然后登录到 Vercel:
vercel login
在项目根目录下,运行:
vercel
Vercel 会检测到这是一个 SvelteKit 项目,并自动进行部署。你可以选择将其部署为公共项目或私有项目,并且可以设置项目的域名等相关配置。
6.3 部署到其他平台
除了 Vercel,你还可以将 SvelteKit 应用部署到 Netlify、GitHub Pages 等其他平台。
部署到 Netlify 与部署到 Vercel 类似,你需要先安装 Netlify CLI,然后登录并运行部署命令。对于 GitHub Pages,你需要在项目设置中配置好构建和发布的相关选项,将 build
目录中的文件发布到 GitHub Pages 服务。
不同平台在部署过程中可能会有一些细微的差异,比如配置环境变量、设置构建命令等,但总体思路都是将构建好的静态文件上传到相应的平台并进行适当的配置。
通过以上步骤,我们就完成了从 SvelteKit 路由基础到构建、与后端集成以及部署一个完整 SvelteKit 应用的全过程。希望这些内容能帮助你更好地理解和使用 SvelteKit 进行前端开发。