SvelteKit:如何进行基于Slug的动态路由?

32

我是一个Svelte和编程的新手。相较于sapper,我更喜欢学习SvelteKit(Svelte@Next),因为它似乎是Svelte发展的方向。

对于我的个人项目,我需要支持基于URL slug的动态路由。在SvelteKit中该如何实现呢?例如,如果我有一个/blog目录并且需要根据其“id”提取内容,我该怎么做呢?

我遇到的困难部分是如何访问URL slug参数。

先谢谢了。


4
考虑到 SvelteKit 尚未发布(并且仍在不断变化),对于这个问题的任何回答可能在实际发布时都是不正确的。 - Stephane Vanraes
1
今天,Sapper使用“preload”函数来访问它的URL参数。一旦SvelteKit完全运行起来,它可能会渲染所有Sapper内容变得老旧且有些不相关。如果在SvelteKit的早期阶段中URL参数的访问方式发生变化,这里的答案可以很容易地进行更新。 - Johny Chen
4个回答

41
自 SvelteKit 1.0 版本起,路径应该是带括号的目录,例如对于 /blog/<slug>,你需要添加以下内容:
src/routes/blog/[slug]
  |_ +page.js
  |_ +page.svelte

然后在 src/routes/blog/[slug]/+page.js 中,您可以添加类似以下内容的代码:

export const load = ({ params }) => {
    return {
        slug: params.slug
    }
}

这将返回一个data属性到+page.svelte,因此您可以编写类似于:

<script>
    export let data;
</script>

<h1>{data.slug}</h1>

参考链接:https://kit.svelte.dev/docs/routing


27

警告:此解决方案已被弃用

  • 您可以使用[括号]创建一个文件:touch src/routes/blog/[slug].svelte

Vscode tree

粘贴以下代码
<script>
    import { page } from '$app/stores';
</script>

{$page.params.slug}

然后导航到您的应用程序 http://localhost:3000/blog/123 您应该看到您的结果

result svelte kit slug

为了为 http://localhost:3000/blog 页面创建内容,您可以修改 src/routes/blog/index.svelte

如何获取路由名称? - chovy
你的路由名称是由你的文件夹结构定义的。如果你的src文件夹中的文件夹名为“my-route”,那么你的URL将会是“{base_url}/my-route”。你是什么意思? - KillianGDK
谢谢你的回答,我很好奇这里的$是什么意思?[在$page变量中] - a3k
1
据我所知,在SvelteKit中,页面是作为存储元素生成的。而在Svelte中,如果您想要访问存储元素,则需要在它们前面加上$符号。页面文档:https://kit.svelte.dev/docs#loading-input-page - KillianGDK
16
这个现在已经被弃用了,请进行更新。 - chovy
3
请查看@isapir的更新答案。 - sutan

4

注意 - 我的回复中的信息可能不适用于SvelteKit不断成熟的版本,但从我迄今为止所做的实验来看,这是有效的:

基于参数的路由与 sveltejs/sapper-template 类似。 首先应该学习 Sapper 是如何做的。 假设我有一个名为 blog 的路由,其中包含单个参数 slug (/blog/page-1 和 /blog/page-2)

  1. 在 routes/blog 中创建一个路由组件,名为 [slug].svelte
  2. 将内容从 sveltejs/sapper-template 示例中复制。
  3. preload 函数重命名为具有单个参数的 load,例如 ctx
  4. 更改返回对象,将您的 slug 属性附加到 props
export async function load(ctx) {
  let slug = ctx.page.params.slug
  return { props: { slug }}
}

如果你的博客的 URL 中有多个参数(例如/blog/2021/01/29/this-is-a-slug),你可以删除 [slug].svelte 文件,并创建一个名为 [...data].svelte 的文件,然后将加载方法更改为:
export async function load(ctx) {
  let [year, month, day, slug] = ctx.page.params.data;
  return { props: { data: { year, month, day, slug }}}
}

不要忘记将您的数据属性定义为对象。以下是一个TypeScript示例:

<script lang="ts">
    export let data: { slug:  string, year: number, month: number, day: number };
</script>

从那里使用值如 {data.slug},等等

愉快地编程吧


当我尝试从[...data]获取不同的参数时,我无法成功。我只能得到一个字符串和其他参数。我正在使用Sveltekit。 - jap1968
感谢您提到 [...data]。这样我就能创建一个 [...path] 目录并匹配所有的 URL。当页面加载时,例如首页的 params.path'',或者嵌套页面的 params.path'use-cases/something' - Jan Švábík

3

我也曾遇到过 TypeScript 导入问题,所以这里提供一个完整的 TypeScript 示例。

结构:

src/routes/coins/[coin_name]
  |_ +page.ts
  |_ +page.svelte

+page.ts:

import type { PageLoad } from './$types';

export const load: PageLoad = ({ params }) => {
    return {
        name: params.coin_name
    }
}

export interface CoinPage{
    name: string
}

+page.svelte 和数据的使用:

<script lang="ts">
    import type { CoinPage } from "./+page";

    export let data:CoinPage;
</script>

<h1>{data.name}</h1>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接