コンテンツにスキップ

タグインデックスページを作成する

各タグの個別ページができたので、それらへのリンクを作成しましょう。

ここで学ぶことは...

  • /pages/folder/index.astroというルーティングパターンを使って新しいページを追加する
  • ユニークなタグのリストを表示し、各タグページにリンクする
  • 新しいタグページへのナビゲーションリンクを追加してサイトを更新する

/pages/folder/index.astroルーティングパターンを使う

ウェブサイトにタグインデックスページを追加するには、新しくsrc/pages/tags.astroを作成します。

しかし、すでに/tags/ディレクトリがあるので、Astroの別のルーティングパターンを利用して、タグに関連するファイルをすべてまとめてみましょう。

やってみよう - タグインデックスページを作る

  1. src/pages/tags/ディレクトリに新しいファイルindex.astroを作成します。

  2. http://localhost:4321/tagsに移動して、サイトにこのURLのページが含まれていることを確認します。中身は空ですが、ページは存在します。

  3. src/pages/tags/index.astroに、レイアウトを使用して最小限のページを作成します。これは以前にもやりましたね!

    手順を表示

    1. src/pages/tags/に新しいページコンポーネントを作成します。

      ファイル名を表示

      index.astro
    2. <BaseLayout>をインポートして使用します。

      コードを表示

      ---
      import BaseLayout from '../../layouts/BaseLayout.astro';
      ---
      <BaseLayout></BaseLayout>
    3. ページタイトルを定義し、コンポーネント属性としてレイアウトに渡します。

      コードを表示

      ---
      import BaseLayout from '../../layouts/BaseLayout.astro';
      const pageTitle = "タグインデックス";
      ---
      <BaseLayout pageTitle={pageTitle}></BaseLayout>
  4. ブラウザのプレビューを再度確認すると、フォーマットされたページが表示されるはずです。これでコンテンツを追加する準備ができました!

タグの配列を作成する

以前もmap()を使って、配列からリストの項目を表示していました。すべてのタグの配列を定義し、このページにリストとして表示するにはどうすればよいでしょうか?

コードを表示

 ---
 import BaseLayout from '../../layouts/BaseLayout.astro';    
 const tags = ['astro', 'ブログ', '公開学習', '成功', 'つまずき', 'コミュニティ']
 const pageTitle = "タグインデックス";
 ---
 <BaseLayout pageTitle={pageTitle}>
   <ul>
     {tags.map((tag) => <li>{tag}</li>)}
   </ul>
 </BaseLayout>

こうすることもできますが、将来ブログ記事で新しいタグを使用するたびに、このファイルに戻って配列を更新しなければいけません。

幸いなことに、1行のコードですべてのMarkdownファイルからデータを取得し、すべてのタグのリストを返す方法をあなたはもう知っているはずです。

  1. src/pages/tags/index.astroのフロントマタースクリプトに、すべての.mdブログ記事ファイルのデータにページからアクセスできるようにするコードを追加します。

    コードを表示

    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    const pageTitle = "タグインデックス";
    ---
  2. 次に、以下のJavaScriptをページコンポーネントに追加します。これは、ユニークなタグのリストを返すためにsrc/pages/tags/[tag].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 = "タグインデックス";
    ---

タグのリストを作成する

今回は順序なしリストの項目を作成するのではなく、<div>の中に各項目の<p>を作成します。お馴染みのパターンですね!

  1. コンポーネントテンプレートに次のコードを追加します。

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

    ブラウザのプレビューで、タグがリスト表示されていることを確認します。ブログ投稿にタグが設定されていない場合や、タグの形式が不適切な場合、TypeScriptによるエラーが表示されます。これによりコードを確認し修正できます。

  2. 各タグをそれぞれのページにリンクさせるには、次の<a>リンクを各タグ名に追加します。

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

タグリストにスタイルを追加する

  1. <div>と生成される各<p>にスタイルを追加するために、次のCSSクラスを記述します。Astroではクラス名を追加するためにHTML構文を使用することに注意してください!

    <BaseLayout pageTitle={pageTitle}>
      <div class="tags">
        {tags.map((tag) => (
          <p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
        ))}
      </div>
    </BaseLayout>
  2. このページに次の<style>タグを追加して、新しいCSSクラスのスタイルを定義します。

    <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. ブラウザのプレビューでhttp://localhost:4321/tagsを開き、新しいスタイルが適用されていること、ページの各タグがそれぞれのタグページへのリンクとして機能していることを確認します。

コードの確認

新しいページのコードは以下のようになっているはずです。

--- 
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 = "タグインデックス";
---
<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>

このページをナビゲーションに追加する

今の時点で、http://localhost:4321/tagsに移動してこのページを表示できます。そしてこのページから、個々のタグページへのリンクをクリックできます。

しかし、このページをウェブサイトの他のページから見つけられるようにする必要がまだあります。

  1. Navigation.astroコンポーネントに、この新しいタグインデックスページへのリンクを追加します。

    コードを表示

    <a href="/">ホーム</a>
    <a href="/about/">概要</a>
    <a href="/blog/">ブログ</a>
    <a href="/tags/">タグ</a>

チャレンジ: ブログ記事レイアウトにタグを含める

これで、ブログの各記事にタグのリストを表示し、タグページにリンクするために必要なすべてのコードを書きましたが、これを再利用して既存のコードで使用してみましょう!

以下の手順に沿って作業を進め、出来上がった自分のコードを最終的なコードサンプルと比較して確認してください。

  1. <div class="tags">...</div><style>...</style>src/pages/tags/index.astroからコピーしてMarkdownPostLayout.astro内で再利用します。

    ---
    import BaseLayout from './BaseLayout.astro';
    const { frontmatter } = Astro.props;
    --- 
    <BaseLayout pageTitle={frontmatter.title}>
      <p>{frontmatter.pubDate.toString().slice(0,10)}</p>
      <p><em>{frontmatter.description}</em></p>
      <p>著者: {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に貼り付けたコードを1箇所だけ編集する必要があります。どこを編集すればいいかわかりますか?

ヒントが欲しい

タイトルや著者など、他のpropsはレイアウトテンプレートでどのように書かれていますか?レイアウトは個々のブログ記事からどのようにpropsを受け取っているでしょうか?

もっとヒントが欲しい

.mdブログ記事から受け取ったタグなどのprops(渡された値)をレイアウトで使用するには、ある単語を値の前に付ける必要があります。

コードを表示

    <div class="tags">
      {frontmatter.tags.map((tag: string) => (
        <p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
      ))}
    </div>

MarkdownPostLayoutのコードの確認

ここまでの自分の作業内容を確認したい場合や、MarkdownPostLayout.astroにコピーするための完全で正しいコードが欲しい場合のために、現段階での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>著者: {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>

確認テスト

与えられたファイルパスと同じルーティングでページを作成する別のファイルパスを選択してください。

  1. src/pages/categories.astro

  2. src/pages/posts.astro

  3. src/pages/products/shoes/index.astro

チェックリスト

参考

貢献する コミュニティ スポンサー