在 SvelteKit 框架中,动态路由的文件夹命名(如[collections]/)决定了 URL 路径段与params对象的映射关系:该路径段会被赋予collections属性(即params.collections),而非自动映射为params.id。若未正确匹配参数名称,params对象可能为空或缺失预期字段,进而导致数据加载失败。
初看之下,这个问题似乎属于基础范畴,但实际排查时却容易让人陷入困惑——尤其是对 SvelteKit 动态路由机制尚不熟悉的开发者。
你遇到的 TypeError: Cannot read properties of undefined (reading 'title'),根本原因在于动态路由参数名与 params 解构方式不一致。SvelteKit 的约定非常清晰:
- 文件夹名
[collections]/意味着该层的 URL 路径段(例如/art/crisis-vision/中的crisis-vision)会被注入到params对象里,键名就是 collections(即params.collections); - 它不会自动映射成 params.id——id 是数据对象内部的字段,与路由参数命名完全是两套逻辑。
因此,+page.server.js 中如果写成这样:
const ret = collections.find((c) => c.id === params.id); // ❌ params.id 不存在!
就等于在寻找一个不存在的属性。params 对象里只包含 collections 属性(比如 params = { collections: 'crisis-vision' }),params.id 自然是 undefined,find() 返回 undefined,最终 data.ret 为空,渲染时便会报错。
✅ 正确的实现方式如下:
// +page.server.js
import { error } from '@sveltejs/kit';
import { collections } from '../data.js';
export function load({ params }) {
const collection = collections.find((c) => c.id === params.collections); // ✅ 使用 params.collections
if (!collection) throw error(404, 'Collection not found');
return { collection }; // 推荐使用语义化字段名,避免嵌套 data.ret
}
相应地,+page.svelte 也需要同步调整:
{data.collection.title}
{@html data.collection.content}
额外建议与注意事项:
- 命名一致性优先:如果你希望使用
params.id,只需将文件夹重命名为[id]/(例如art/[id]/+page.server.js),这样params.id才会真正生效; - 始终校验数据存在性:
find()可能返回undefined,添加if (!collection) throw error(404)能有效防范隐藏的异常; - 避免深层嵌套返回值:直接返回
{ collection }比返回{ ret }更直观、更易于维护; - 开发时调试技巧:在
load函数中插入一行console.log({ params }),可以快速验证参数结构是否正确。
只要彻底理解参数命名映射规则,这个“空参数”问题便能迎刃而解,动态路由的数据加载也会变得稳定可靠。
