初めてのレイアウトを作成する
ここで学ぶことは...
- 共通要素をページレイアウトにリファクタリングする
- Astroの
<slot />要素を使用して、ページの内容をレイアウト内に配置する - ページ固有の値をレイアウトにpropsとして渡す
まだいくつかのAstroコンポーネントが各ページで繰り返しレンダリングされています。さらにリファクタリングを進めて、共通のページレイアウトを作成しましょう!
初めてのレイアウトコンポーネントを作成する
src/layouts/BaseLayout.astroに新しいファイルを作成します。(まず新しいlayoutsフォルダを作成する必要があります。)index.astroのすべてのコンテンツを新しいファイルBaseLayout.astroにコピーします。--- import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; import '../styles/global.css'; const pageTitle = "ホームページ"; --- <html lang="ja"> <head> <meta charset="utf-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width" /> <meta name="generator" content={Astro.generator} /> <title>{pageTitle}</title> </head> <body> <Header /> <h1>{pageTitle}</h1> <Footer /> <script> import "../scripts/menu.js"; </script> </body> </html>
レイアウトをページで使用する
src/pages/index.astroのコードを以下に置き換えます。--- import BaseLayout from '../layouts/BaseLayout.astro'; const pageTitle = "Home Page"; --- <BaseLayout> <h2>私の素晴らしいブログのサブタイトル</h2> </BaseLayout>ブラウザのプレビューを再度開いて、何が変わったか(あるいは、ネタバレになりますが、何が変わっていないか)を確認します。
src/layouts/BaseLayout.astroのフッターコンポーネントの直前に<slot />要素を追加し、ブラウザのプレビューでホームページを開いて、今度はどこが変わったのかを確認します!--- import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; import '../styles/global.css'; const pageTitle = "ホームページ"; --- <html lang="ja"> <head> <meta charset="utf-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width" /> <meta name="generator" content={Astro.generator} /> <title>{pageTitle}</title> </head> <body> <Header /> <h1>{pageTitle}</h1> <slot /> <Footer /> <script> import "../scripts/menu.js"; </script> </body> </html>
<slot />を使うと、<Component></Component>の開始タグと終了タグの間に書かれた子コンテンツを、Component.astroファイルに挿入(または「スロットイン、slot in」)できるのです。
ページ固有の値をpropsとして渡す
index.astroで、コンポーネント属性を使ってレイアウトコンポーネントにページタイトルを渡します。--- import BaseLayout from '../layouts/BaseLayout.astro'; const pageTitle = "ホームページ"; --- <BaseLayout pageTitle={pageTitle}> <h2>私の素晴らしいブログのサブタイトル</h2> </BaseLayout>BaseLayout.astroレイアウトコンポーネントのスクリプトを、ページタイトルを定数として定義するのではなく、Astro.propsを介して受け取るように変更します。--- import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; import '../styles/global.css'; const pageTitle = "ホームページ"; const { pageTitle } = Astro.props; ---ブラウザのプレビューを開き、ページタイトルが変わっていないことを確認します。値は同じですが、実際は動的にレンダリングされています。また、各ページは自身のタイトルをレイアウトに対して指定できるようになりました。
やってみよう - レイアウトをすべてのページで使用する
他のblog.astroとabout.astroページをリファクタリングし、<BaseLayout>コンポーネントを使って共通のページ要素をレンダリングするようにしましょう。
以下を忘れないでください。
コンポーネント属性を介してページタイトルをpropsとして渡します。
共通要素のHTMLレンダリングをレイアウトに任せます。
ページの
<head>内にある既存の<style>タグを、保持したいスタイルとともにページのHTMLテンプレートに移動します。各ページから、レイアウトにより処理されるようになったものを削除します。
- HTML要素
- コンポーネントとそのインポート文
<style>タグ内のCSSルール、たとえば概要ページの<h1>など<script>タグ
:::note[概要ページのスタイルを保持する]about.astroページをレンダリングするためにBaseLayoutを使用すると、このページの<head>に追加された<style>タグが失われます。Astroのスコープ付きスタイリングを使用して、ページレベルでのみスタイルを適用し続けるには、<style>タグをページコンポーネントのbodyに移動してください。これにより、このページコンポーネントで作成された要素(たとえば、スキルリスト)をスタイルできます。
<h1>はレイアウトコンポーネントにより作成されるようになったので、他のコンポーネントにより作成される要素を含むこのページのすべての要素に影響を与えるように、スタイルタグに<style is:global define:vars={{ skillColor, fontWeight, textCase }}>のようにis:global属性を追加できます。:::
確認テスト
Astroコンポーネント(
.astroファイル)の機能は以下のうちどれですか?ページタイトルをページに表示するにはどうすればいいですか?
あるコンポーネントから別のコンポーネントに情報を渡すにはどうすればいいですか?