在11ty中动态路由参数怎么传递不到模板里?

西门书妍 阅读 38

在用11ty做SSR博客时,我按文档写了动态路由/posts/{slug},但模板里用page.slug总拿不到参数值。

我试过把数据文件放在_posts文件夹,配置了eleventyComputed动态设置路径,但访问/posts/test-post时页面显示undefined。检查了frontmatter和数据收集配置都没问题,这是哪里漏了吗?


// .eleventy.js配置
module.exports = function() {
  return {
    dir: { input: "src" },
    templateFormats: ["njk", "md", "html"],
    pathPrefix: "/",
    // 尝试过的路由配置
    routeParams: function(slug) {
      return { slug };
    }
  };
};

模板文件用的是posts/*.html的集合,但控制台报错Cannot read properties of undefined (reading 'slug'),明明文件结构没问题啊…

我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
书生シ蒙蒙
你这问题是典型的11ty动态路由配置没对齐,前端想拿后端没给的数据。别急,改一下就行。

问题出在你的 routeParams 配置上,11ty里这个方法根本不会自动把参数传到模板里。你需要用 eleventyComputed 来动态生成数据。

试试下面的配置:

// .eleventy.js
module.exports = function (eleventyConfig) {
return {
dir: { input: "src" },
templateFormats: ["njk", "md", "html"],
pathPrefix: "/",
dataTemplateEngine: "njk", // 确保能解析模板数据
markdownTemplateEngine: "njk",
htmlTemplateEngine: "njk",
passthroughFileCopy: true,
eleventyComputed: {
permalink: (data) => /posts/${data.page.fileSlug}/, // 动态设置permalink
slug: (data) => data.page.fileSlug // 把slug注入到data里
}
};
};


然后在模板里直接用 {{ page.fileSlug }} 就行了,别再用 page.slug,那个是你之前瞎折腾留下的坑。

最后检查下文件结构,确保是这样的:
/src/posts/test-post.md
访问 /posts/test-post 就能正确拿到参数了。

实在不行就重启项目,有时候缓存也坑人。
点赞 12
2026-02-02 12:14
夏侯兴慧
这个问题我遇到过,11ty的动态路由确实有点绕。你的情况应该是page.slug拿不到值的问题,主要是因为配置和数据传递的方式没对上。别急,我分步骤给你捋清楚。

### 1. 首先确认一下你的文件结构
11ty的动态参数是通过文件名和路径解析出来的,假设你的文件结构是这样的:
src/
├── _posts/
│ ├── test-post.md
│ └── another-post.md

那么test-post.md会被解析成/posts/test-post。如果你的文件不在_posts目录下,或者命名不规范(比如带后缀以外的东西),可能会导致slug解析不出来。

**注意**:11ty默认会把文件名去掉扩展名作为slug,所以test-post.md对应的slug就是test-post

---

### 2. 检查.eleventy.js的配置
你的配置里写了routeParams,但这个方法不是用来设置slug的,而是用来传递额外的参数。slug的生成规则其实是由文件路径决定的。你需要在配置里明确告诉11ty怎么处理这些文件。

修改你的.eleventy.js配置如下:
module.exports = function(eleventyConfig) {
return {
dir: { input: "src" },
templateFormats: ["njk", "md", "html"],
pathPrefix: "/",

// 这里添加markdown模板的数据传递逻辑
markdownTemplateEngine: "njk",
htmlTemplateEngine: "njk",
dataTemplateEngine: "njk",

// 添加集合定义,把_posts目录下的文件归类
collections: {
posts: function(collectionApi) {
return collectionApi.getFilteredByGlob("_posts/*.md");
}
},

// 添加一个computed属性,让每篇文章都能正确获取slug
eleventyComputed: {
permalink(data) {
if (data.page.fileSlug) {
return /posts/${data.page.fileSlug}/;
}
return null;
},
slug(data) {
return data.page.fileSlug; // 直接用fileSlug作为slug
}
}
};
};


**原理是这样**:eleventyComputed是一个全局配置,它会在每篇文章渲染时自动计算一些值。我们这里定义了两个属性:
- permalink:用来设置文章的最终路径。
- slug:直接从data.page.fileSlug取值,确保每个页面都有正确的slug。

---

### 3. 修改模板文件
接下来检查你的模板文件。假设你有一个posts.njk模板,用来渲染所有文章列表:

<ul>
{% for post in collections.posts %}
<li>
<a href="{{ post.url }}">{{ post.data.title }}</a> <!-- 注意这里用post.url -->
<small>Slug: {{ post.data.slug }}</small>
</li>
{% endfor %}
</ul>


单个文章详情页的模板(比如_posts/test-post.md对应的)可以这样写:
---
title: "测试文章"
date: "2023-01-01"
---

<h1>{{ title }}</h1>
<p>Slug: {{ page.slug }}</p> <!-- 这里就可以拿到slug -->
{{ content | safe }}


**关键点**:
- page.slug是在eleventyComputed里定义的,确保每个页面都有这个值。
- 如果你在循环里用collections.posts,记得通过post.data访问自定义字段。

---

### 4. 常见坑点排查
如果你还是拿不到page.slug,可能是以下原因:
1. **文件名不对**:确保你的Markdown文件名没有奇怪的字符或多余后缀,比如test-post.md是对的,test-post.en.md可能会有问题。
2. **集合没匹配到**:检查collections.posts是否真的包含了你的文章,可以在开发模式下打印看看:
console.log(collections.posts);

3. **配置冲突**:如果你同时用了其他插件或配置,可能会覆盖掉eleventyComputed的设置。

---

### 5. 最后验证一下
重启你的开发服务器,访问/posts/test-post,应该能看到页面正常显示slug的值了。如果还有问题,可以把具体的报错或文件结构贴出来,我再帮你看看。

希望这能帮到你!动态路由这块确实容易踩坑,慢慢调试就顺了。
点赞 4
2026-01-29 04:01