返回介绍

生成标签页面

发布于 2024-06-05 21:19:57 字数 13596 浏览 0 评论 0 收藏 0

准备好…

  • 创建一个页面以生成多个页面
  • 指定要构建的页面路由,并为每个页面传递各自的属性

动态页面路由

你可以使用 .astro 文件创建整套动态页面,这些文件需要向外暴露一个 getStaticPaths() 函数。

动态创建页面

  1. 创建一个新文件: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>包含「{tag}」标签的文章</p>
    </BaseLayout>

    getStaticPaths 函数返回一个页面路由数组,这些页面将使用文件中定义的相同模板。

  2. 如果你已经自定义了博客文章,用你自己的文章中使用的标签替换各个标签值(例如 “astro”、“successes”、“community” 等)。

  3. 确保每篇博客文章至少包含一个标签,以数组的形式编写,例如 tags: ["blogging"]

  4. 在浏览器中访问 http://localhost:4321/tags/astro,你应该能看到一个页面,它是从 [tag].astro 动态生成的。检查是否还为每个标签创建了页面,例如 /tags/successes/tags/community/tags/learning%20in%20public 等,或者你自定义的标签。你可能需要先退出并重新启动开发服务器才能看到这些新页面。

在动态路由中使用 props

  1. 在你的 getStaticPaths() 函数中添加以下 props,以便使所有博客文章的数据对每个页面路由可用。

    确保为数组中的每个路由都添加新的 props,并将这些 props 在函数之外的组件模板中可用。

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    
    
    export async function getStaticPaths() {  const allPosts = await Astro.glob('../posts/*.md');
    
    
      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;
    ---
  2. 将文章列表筛选为仅包含页面所属标签的文章。

    /src/pages/tags/[tag].astro
    ---
    const { tag } = Astro.params;
    const { posts } = Astro.props;const filteredPosts = posts.filter((post) => post.frontmatter.tags?.includes(tag));
    ---
  3. 现在,你可以更新 HTML 模板以显示包含页面所属标签的每篇博客文章列表。将以下代码添加到 [tag].astro

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
      <p>包含「{tag}」标签的文章</p>  <ul>    {filteredPosts.map((post) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}  </ul>
    </BaseLayout>
  4. 你甚至可以将此代码重构为使用 <BlogPost /> 组件!(不要忘记在 [tag].astro 的顶部导入该组件。)

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
      <p>包含「{tag}」标签的文章</p>
      <ul>    {filteredPosts.map((post) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}    {filteredPosts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
      </ul>
    </BaseLayout>
  5. 在浏览器中的预览中查看各个标签页面,现在你应该能看到包含特定标签的所有博客文章列表。

分析代码

对于以下每个问题,请指出代码是在 getStaticPath() 函数的内部还是在其外部编写的。

  1. Astro.glob() 调用以接收有关所有 .md 文件的信息,并将其传递给每个页面路由。

  2. getStaticPaths() 要生成(返回的)路由列表的代码。

  3. 用于在 HTML 模板中使用的 propsparams 的值。

进阶 JavaScript:从现有标签生成页面

现在,你的标签页面在 [tag].astro 中静态定义。如果你在博客文章中添加了新标签,你还必须重新访问该页面并更新你的页面路由。

以下示例显示了如何用新的代码替换此页面上的代码,该代码将自动查找并为博客页面上使用的每个标签生成页面。

  1. 检查所有博客文章是否包含标签

    重新访问你的现有 Markdown 页面,确保每篇文章的前置数据中都包含一个 tags 数组。即使只有一个标签,它也应该被写成一个数组,例如 tags: ["blogging"]

  2. 创建包含所有现有标签的数组

    添加以下代码,以提供一个包含博客文章中使用的每个标签的列表。

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    
    
    export async function getStaticPaths() {
      const allPosts = await Astro.glob('../posts/*.md');
    
      const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];
    请详细说明这行代码正在做什么!

    毕竟这不是你自己编写的代码,看不懂是正常的!

    它逐个处理每个 Markdown 文章,并将每个标签数组组合成一个更大的数组。然后,它从找到的所有标签创建一个新的 Set(以忽略重复值)。最后,它将该 Set 转换为一个数组(不重复的),你可以用它来显示页面上的标签列表。

    现在,你有一个名为 uniqueTags 的数组,其中包含元素项 "astro""successes""community""blogging""setbacks""learning in public"

  3. 替换 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) => 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) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}    {posts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
    </ul>

最终代码示例

为了检查你的工作,或者如果你只想要完整、正确的代码以便复制到 [tag].astro 文件中,下面是你的 Astro 组件应该是这样的:

src/pages/tags/[tag].astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import BlogPost from '../../components/BlogPost.astro';


export async function getStaticPaths() {
  const allPosts = await Astro.glob('../posts/*.md');


  const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];


  return uniqueTags.map((tag) => {
    const filteredPosts = allPosts.filter((post) => post.frontmatter.tags.includes(tag));
    return {
      params: { tag },
      props: { posts: filteredPosts },
    };
  });
}


const { tag } = Astro.params;
const { posts } = Astro.props;
---
<BaseLayout pageTitle={tag}>
  <p>包含「{tag}」标签的文章</p>
  <ul>
    {posts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
  </ul>
</BaseLayout>

现在,你应该能够在浏览器预览中访问任何一个标签页面。

在浏览器中导航到 http://localhost:4321/tags/community,你应该看到一个包含标签为 community 的博文列表。同样地,http://localhost:4321/tags/learning%20in%20public 应该显示一个包含标签为 learning in public 的博文列表。

在接下来的部分,你将创建导航链接到这些页面。

检验你的知识

选择与描述相匹配的术语。

  1. 返回一个页面路由数组的函数。

  2. 从一个文件中创建多个页面路由的过程。

  3. 定义动态生成的页面路由名称的值。

任务清单

相关资源

Tutorials

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文