生成标签页面
准备好去……
- 创建一个页面来生成多个页面
- 指定要构建的页面路由,并为每个页面传递其自己的 props
动态页面路由
标题为“动态页面路由”的部分你可以使用导出 getStaticPaths()
函数的 .astro
文件动态创建整套页面。
动态创建页面
标题为“动态创建页面”的部分-
在
src/pages/tags/[tag].astro
创建一个新文件。(你需要创建一个新文件夹。)请注意,文件名([tag].astro
)使用了方括号。将以下代码粘贴到该文件中src/pages/tags/[tag].astro ---import BaseLayout from '../../layouts/BaseLayout.astro';export async function getStaticPaths() {return [{ params: { tag: "astro" } },{ params: { tag: "successes" } },{ params: { tag: "community" } },{ params: { tag: "blogging" } },{ params: { tag: "setbacks" } },{ params: { tag: "learning in public" } },];}const { tag } = Astro.params;---<BaseLayout pageTitle={tag}><p>Posts tagged with {tag}</p></BaseLayout>getStaticPaths
函数返回一个页面路由数组,所有这些路由上的页面都将使用该文件中定义的相同模板。 -
如果你自定义了博客文章,请将各个标签值(例如“astro”、“successes”、“community”等)替换为你自己文章中使用的标签。
-
请确保每篇博客文章都包含至少一个标签,并以数组形式编写,例如
tags: ["blogging"]
。 -
在浏览器预览中访问
https://:4321/tags/astro
,你应该会看到一个由[tag].astro
动态生成的页面。检查你是否也为每个标签创建了页面,例如/tags/successes
、/tags/community
和/tags/learning%20in%20public
等,或者为你自定义的每个标签创建了页面。你可能需要先退出并重启开发服务器才能看到这些新页面。
在动态路由中使用 props
标题为“在动态路由中使用 props”的部分-
将以下 props 添加到你的
getStaticPaths()
函数中,以便让你所有博客文章的数据对每个页面路由都可用。请确保为数组中的每个路由提供新的 props,然后在函数外部使这些 props 对你的组件模板可用。
src/pages/tags/[tag].astro ---import BaseLayout from '../../layouts/BaseLayout.astro';export async function getStaticPaths() {const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));return [{params: {tag: "astro"}, props: {posts: allPosts}},{params: {tag: "successes"}, props: {posts: allPosts}},{params: {tag: "community"}, props: {posts: allPosts}},{params: {tag: "blogging"}, props: {posts: allPosts}},{params: {tag: "setbacks"}, props: {posts: allPosts}},{params: {tag: "learning in public"}, props: {posts: allPosts}}];}const { tag } = Astro.params;const { posts } = Astro.props;--- -
使用 Astro 内置的 TypeScript 支持来筛选你的文章列表,使其仅包含带有页面自身标签的文章。
src/pages/tags/[tag].astro ---const { tag } = Astro.params;const { posts } = Astro.props;const filteredPosts = posts.filter((post: any) => post.frontmatter.tags?.includes(tag));--- -
现在你可以更新你的 HTML 模板,以显示包含页面自身标签的每篇博客文章的列表。将以下代码添加到
[tag].astro
src/pages/tags/[tag].astro <BaseLayout pageTitle={tag}><p>Posts tagged with {tag}</p><ul>{filteredPosts.map((post: any) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}</ul></BaseLayout> -
你甚至可以将其重构为使用你的
<BlogPost />
组件!(别忘了在[tag].astro
的顶部导入此组件。)src/pages/tags/[tag].astro <BaseLayout pageTitle={tag}><p>Posts tagged with {tag}</p><ul>{filteredPosts.map((post: any) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}{filteredPosts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}</ul></BaseLayout> -
在浏览器预览中检查你的各个标签页,现在你应该能看到一个包含该特定标签的所有博客文章的列表。
分析模式
标题为“分析模式”的部分对于以下各项,请说明代码是写在 getStaticPaths()
函数的内部还是外部。
-
用于接收所有
.md
文件信息以传递给每个页面路由的import.meta.glob()
调用。 -
由
getStaticPaths()
生成(返回)的路由列表 -
在 HTML 模板中使用的接收到的
props
和params
的值。
如果你需要信息来构建页面路由,请将其写在 getStaticPaths()
内部。
要在页面路由的 HTML 模板中接收信息,请将其写在 getStaticPaths()
外部。
高级 JavaScript:从现有标签生成页面
标题为“高级 JavaScript:从现有标签生成页面”的部分你的标签页现在是在 [tag].astro
中静态定义的。如果你向博客文章添加新标签,你还必须重新访问此页面并更新你的页面路由。
下面的示例展示了如何用新代码替换此页面上的代码,新代码将自动查找并为博客页面上使用的每个标签生成页面。
即使它看起来有挑战性,你也可以尝试按照步骤自己构建此函数!如果你现在不想逐步了解所需的 JavaScript,可以跳到最终版本的代码,并直接在你的项目中使用它,替换现有内容。
-
检查所有博客文章是否都包含标签
重新访问你现有的每个 Markdown 页面,并确保每篇文章的 frontmatter 中都包含一个
tags
数组。即使你只有一个标签,它也应该写成数组形式,例如tags: ["blogging"]
。 -
使用 Astro 内置的 TypeScript 支持创建一个包含所有现有标签的数组。
添加以下代码,以提供一个包含你博客文章中使用的每个标签的列表。
src/pages/tags/[tag].astro ---import BaseLayout from '../../layouts/BaseLayout.astro';export async function getStaticPaths() {const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));const uniqueTags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];}更详细地告诉我这行代码在做什么!
如果你自己还写不出这样的代码,也没关系!
它会逐一遍历每篇 Markdown 文章,并将每个标签数组合并成一个更大的数组。然后,它会用找到的所有单个标签创建一个新的
Set
(以忽略重复的值)。最后,它将该集合转换成一个数组(没有重复项),你可以用它在页面上显示标签列表。现在你有了一个数组
uniqueTags
,其元素为"astro"
、"successes"
、"community"
、"blogging"
、"setbacks"
、"learning in public"
-
替换
getStaticPaths
函数的return
值src/pages/tags/[tag].astro return [{params: {tag: "astro"}, props: {posts: allPosts}},{params: {tag: "successes"}, props: {posts: allPosts}},{params: {tag: "community"}, props: {posts: allPosts}},{params: {tag: "blogging"}, props: {posts: allPosts}},{params: {tag: "setbacks"}, props: {posts: allPosts}},{params: {tag: "learning in public"}, props: {posts: allPosts}}]return uniqueTags.map((tag) => {const filteredPosts = allPosts.filter((post: any) => post.frontmatter.tags.includes(tag));return {params: { tag },props: { posts: filteredPosts },};}); -
一个
getStaticPaths
函数应始终返回一个对象列表,其中包含params
(如何命名每个页面路由)和可选的任何props
(你想传递给这些页面的数据)。之前,你定义了你知道在博客中使用的每个标签名,并将整个文章列表作为 props 传递给了每个页面。现在,你使用
uniqueTags
数组自动生成这个对象列表,以定义每个参数。并且,现在所有博客文章的列表在作为 props 发送到每个页面之前就被过滤了。请务必删除之前过滤文章的那行代码,并更新你的 HTML 模板,使用
posts
而不是filteredPosts
。src/pages/tags/[tag].astro const { tag } = Astro.params;const { posts } = Astro.props;const filteredPosts = posts.filter((post) => post.frontmatter.tags?.includes(tag));---<!-- --><ul>{filteredPosts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}{posts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}</ul>
最终代码示例
标题为“最终代码示例”的部分为了检查你的工作,或者如果你只是想将完整、正确的代码复制到 [tag].astro
中,这里是你的 Astro 组件应该有的样子
---import BaseLayout from '../../layouts/BaseLayout.astro';import BlogPost from '../../components/BlogPost.astro';
export async function getStaticPaths() { const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
const uniqueTags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];
return uniqueTags.map((tag) => { const filteredPosts = allPosts.filter((post: any) => post.frontmatter.tags.includes(tag)); return { params: { tag }, props: { posts: filteredPosts }, }; });}
const { tag } = Astro.params;const { posts } = Astro.props;---<BaseLayout pageTitle={tag}> <p>Posts tagged with {tag}</p> <ul> {posts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)} </ul></BaseLayout>
现在,你应该可以在浏览器预览中访问你的任何标签页了。
导航到 https://:4321/tags/community
,你应该只会看到带有 community
标签的博客文章列表。同样,https://:4321/tags/learning%20in%20public
应该会显示带有 learning in public
标签的博客文章列表。
在下一节中,你将创建到这些页面的导航链接。
知识测验
标题为“测试你的知识”的部分选择与描述匹配的术语。
-
一个返回页面路由数组的函数。
-
在 Astro 中从一个文件创建多个页面路由的过程。
-
一个定义动态生成的页面路由名称的值。