Skip to content

建立标签索引页面

现在每个标签都有单独的页面,是时候为它们建立链接了。

¥Now that you have individual pages for every tag, it’s time to make links to them.

准备好……

  • 使用 /pages/folder/index.astro 路由模式添加新页面

  • 显示所有独特标签的列表,链接到每个标签页面

  • 使用指向此新标签页面的导航链接更新你的网站

使用 /pages/folder/index.astro 路由模式

标题部分 使用 /pages/folder/index.astro 路由模式

¥Use the /pages/folder/index.astro routing pattern

要将标签索引页面添加到你的网站,你可以在 src/pages/tags.astro 创建一个新文件。

¥To add a Tag Index page to your website, you could create a new file at src/pages/tags.astro.

但是,由于你已经有了目录 /tags/,因此你可以利用 Astro 中的另一种路由模式,并将与标签相关的所有文件保存在一起。

¥But, since you already have the directory /tags/, you can take advantage of another routing pattern in Astro, and keep all your files related to tags together.

自己尝试一下 - 制作标签索引页

标题部分 自己尝试一下 - 制作标签索引页

¥Try it yourself - Make a Tag Index page

  1. Create a new file index.astro in the directory src/pages/tags/.

  2. Navigate to http://localhost:4321/tags and verify that your site now contains a page at this URL. It will be empty, but it will exist.

  3. Create a minimal page at src/pages/tags/index.astro that uses your layout. You have done this before!

    Expand to see the steps
    1. Create a new page component in src/pages/tags/.

      Show the filename
      index.astro
    2. Import and use your <BaseLayout>.

      Show the code
      src/pages/tags/index.astro
      ---
      import BaseLayout from '../../layouts/BaseLayout.astro';
      ---
      <BaseLayout></BaseLayout>
    3. Define a page title, and pass it to your layout as a component attribute.

      Show the code
      src/pages/tags/index.astro
      ---
      import BaseLayout from '../../layouts/BaseLayout.astro';
      const pageTitle = "Tag Index";
      ---
      <BaseLayout pageTitle={pageTitle}></BaseLayout>
  4. Check your browser preview again and you should have a formatted page, ready to add content to!

¥Create an array of tags

你之前已使用 map() 显示了数组中列表中的项目。定义所有标签的数组,然后将它们显示在此页面的列表中会是什么样子?

¥You have previously displayed items in a list from an array using map(). What would it look like to define an array of all your tags, then display them in a list on this page?

See the code
src/pages/tags/index.astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
const tags = ['astro', 'blogging', 'learning in public', 'successes', 'setbacks', 'community']
const pageTitle = "Tag Index";
---
<BaseLayout pageTitle={pageTitle}>
<ul>
{tags.map((tag) => <li>{tag}</li>)}
</ul>
</BaseLayout>

你可以这样做,但是每次你在以后的博客文章中使用新标签时,你都需要返回到该文件并更新你的数组。

¥You could do this, but then you would need to come back to this file and update your array every time you use a new tag in a future blog post.

幸运的是,你已经知道一种方法,可以通过一行代码从所有 Markdown 文件中获取数据,然后返回所有标签的列表。

¥Fortunately, you already know a way to grab the data from all your Markdown files in one line of code, then return a list of all your tags.

  1. In src/pages/tags/index.astro, add the line of code to the frontmatter script that will give your page access to the data from every .md blog post file.

    See the code
    src/pages/tags/index.astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    const pageTitle = "Tag Index";
    ---
  2. Next, add the following line of JavaScript to your page component. This is the same code relying on Astro’s built-in TypeScript support you used in src/pages/tags/[tag].astro to return a list of unique tags.

    src/pages/tags/index.astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    const tags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];
    const pageTitle = "Tag Index";
    ---

¥Create your list of tags

这次不是在无序列表中创建项目,而是在 <div> 内为每个项目创建一个 <p>。这个图案应该看起来很熟悉!

¥Instead of creating items in an unordered list this time, create one <p> for each item, inside a <div>. The pattern should look familiar!

  1. Add the following code to your component template:

    src/pages/tags/index.astro
    <BaseLayout pageTitle={pageTitle}>
    <div>{tags.map((tag) => <p>{tag}</p>)}</div>
    </BaseLayout>

    In your browser preview, verify that you can see your tags listed. If any blog posts are missing tags, or they are improperly formatted, Astro’s built-in TypeScript support will show you errors so you can check and correct your code.

  2. To make each tag link to its own page, add the following <a> link to each tag name:

    src/pages/tags/index.astro
    <BaseLayout pageTitle={pageTitle}>
    <div>
    {tags.map((tag) => (
    <p><a href={`/tags/${tag}`}>{tag}</a></p>
    ))}
    </div>
    </BaseLayout>

将样式添加到标签列表

标题部分 将样式添加到标签列表

¥Add styles to your tag list

  1. Add the following CSS classes to style both your <div> and each <p> that will be generated. Note: Astro uses HTML syntax for adding class names!

    src/pages/tags/index.astro
    <BaseLayout pageTitle={pageTitle}>
    <div class="tags">
    {tags.map((tag) => (
    <p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
    ))}
    </div>
    </BaseLayout>
  2. Define these new CSS classes by adding the following <style> tag to this page:

    src/pages/tags/index.astro
    <style>
    a {
    color: #00539F;
    }
    .tags {
    display: flex;
    flex-wrap: wrap;
    }
    .tag {
    margin: 0.25em;
    border: dotted 1px #a1a1a1;
    border-radius: .5em;
    padding: .5em 1em;
    font-size: 1.15em;
    background-color: #F8FCFD;
    }
    </style>
  3. Check your browser preview at http://localhost:4321/tags to verify that you have some new styles and that each of the tags on the page has a working link to its own individual tag page.

¥Code Check-In

你的新页面应如下所示:

¥Here is what your new page should look like:

src/pages/tags/index.astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
const tags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];
const pageTitle = "Tag Index";
---
<BaseLayout pageTitle={pageTitle}>
<div class="tags">
{tags.map((tag) => (
<p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
))}
</div>
</BaseLayout>
<style>
a {
color: #00539F;
}
.tags {
display: flex;
flex-wrap: wrap;
}
.tag {
margin: 0.25em;
border: dotted 1px #a1a1a1;
border-radius: .5em;
padding: .5em 1em;
font-size: 1.15em;
background-color: #F8FCFD;
}
</style>

将此页面添加到你的导航中

标题部分 将此页面添加到你的导航中

¥Add this page to your navigation

现在,你可以导航到 http://localhost:4321/tags 并查看此页面。在此页面中,你可以单击指向个人标签页面的链接。

¥Right now, you can navigate to http://localhost:4321/tags and see this page. From this page, you can click on links to your individual tag pages.

但是,你仍然需要使这些页面可以从你网站上的其他页面发现。

¥But, you still need to make these pages discoverable from other pages on your website.

  1. In your Navigation.astro component, include a link to this new tag index page.

    Show me the code
    src/components/Navigation.astro
    <a href="/">Home</a>
    <a href="/about/">About</a>
    <a href="/blog/">Blog</a>
    <a href="/tags/">Tags</a>

挑战:在你的博客文章布局中包含标签

标题部分 挑战:在你的博客文章布局中包含标签

¥Challenge: Include tags in your blog post layout

你现在已经编写了在每篇博客文章上显示标签列表并将它们链接到其标签页面所需的所有代码。你有可以重复使用的现有作品!

¥You have now written all the code you need to also display a list of tags on each blog post, and link them to their tag pages. You have existing work that you can reuse!

按照以下步骤操作,然后通过与 最终代码示例 进行比较来检查你的工作。

¥Follow the steps below, then check your work by comparing it to the final code sample.

  1. Copy the <div class="tags">...</div> and <style>...</style> from src/pages/tags/index.astro and reuse it inside MarkdownPostLayout.astro:

    src/layouts/MarkdownPostLayout.astro
    ---
    import BaseLayout from './BaseLayout.astro';
    const { frontmatter } = Astro.props;
    ---
    <BaseLayout pageTitle={frontmatter.title}>
    <p><em>{frontmatter.description}</em></p>
    <p>{frontmatter.pubDate.toString().slice(0,10)}</p>
    <p>Written by: {frontmatter.author}</p>
    <img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
    <div class="tags">
    {tags.map((tag: string) => (
    <p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
    ))}
    </div>
    <slot />
    </BaseLayout>
    <style>
    a {
    color: #00539F;
    }
    .tags {
    display: flex;
    flex-wrap: wrap;
    }
    .tag {
    margin: 0.25em;
    border: dotted 1px #a1a1a1;
    border-radius: .5em;
    padding: .5em 1em;
    font-size: 1.15em;
    background-color: #F8FCFD;
    }
    </style>

在此代码运行之前,你需要对粘贴到 MarkdownPostLayout.astro 中的代码进行一个小的编辑。你能弄清楚它是什么吗?

¥Before this code will work, you need to make one small edit to the code you pasted into MarkdownPostLayout.astro. Can you figure out what it is?

Give me a hint

其他属性(例如标题、作者等)是如何在你的布局模板中编写的?你的布局如何从单个博客文章接收 props?

¥How are the other props (e.g. title, author, etc.) written in your layout template? How does your layout receive props from an individual blog post?

Give me another hint!

为了在你的布局中使用来自 .md 博客文章的 props(传递的值),如标签,你需要在值前加上某个单词。

¥In order to use props (values passed) from a .md blog post in your layout, like tags, you need to prefix the value with a certain word.

Show me the code!
src/layouts/MarkdownPostLayout.astro
<div class="tags">
{frontmatter.tags.map((tag: string) => (
<p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
))}
</div>

代码签到:MarkdownPostLayout

标题部分 代码签到:MarkdownPostLayout

¥Code Check-in: MarkdownPostLayout

要检查你的工作,或者如果你只是想将完整、正确的代码复制到 MarkdownPostLayout.astro 中,你的 Astro 组件应如下所示:

¥To check your work, or if you just want complete, correct code to copy into MarkdownPostLayout.astro, here is what your Astro component should look like:

src/layouts/MarkdownPostLayout.astro
---
import BaseLayout from './BaseLayout.astro';
const { frontmatter } = Astro.props;
---
<BaseLayout pageTitle={frontmatter.title}>
<p><em>{frontmatter.description}</em></p>
<p>{frontmatter.pubDate.toString().slice(0,10)}</p>
<p>Written by: {frontmatter.author}</p>
<img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
<div class="tags">
{frontmatter.tags.map((tag: string) => (
<p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
))}
</div>
<slot />
</BaseLayout>
<style>
a {
color: #00539F;
}
.tags {
display: flex;
flex-wrap: wrap;
}
.tag {
margin: 0.25em;
border: dotted 1px #a1a1a1;
border-radius: .5em;
padding: .5em 1em;
font-size: 1.15em;
background-color: #F8FCFD;
}
</style>

¥Test your knowledge

将每个文件路径与第二个文件路径匹配,这将在同一路径上创建页面。

¥Match each file path with a second file path that will create a page at the same route.

  1. src/pages/categories.astro
  1. src/pages/posts.astro
  1. src/pages/products/shoes/index.astro

¥Checklist

¥Resources

Astro 中文网 - 粤ICP备13048890号