[go: up one dir, main page]

コンテンツにスキップ

テンプレートディレクティブの概要

Astroではテンプレートディレクティブと呼ばれる特別なHTML属性が用意されています。これらは主にAstroコンポーネント(.astroファイル)のテンプレート内で使えますが、一部は.mdxファイルでも使用可能です。

テンプレートディレクティブの役割は、要素やコンポーネントの挙動をコントロールすることです。例えば、開発をより楽にするコンパイラ機能(classの代わりにclass:listを使うなど)を有効にしたり、Astroコンパイラに特別な指示(client:loadでクライアントサイドの機能を有効にするなど)を出したりします。

このページでは、Astroで使えるすべてのテンプレートディレクティブとその働きについて詳しく解説します。

テンプレートディレクティブを正しく使うには、以下の2つの条件を満たす必要があります。

  1. 名前にコロン(:)を含めること。例えば「X:Y」のような形式です(例:client:load)。
  2. コンパイラから認識できる位置に書くこと。例えば、<X {...attr}>のように書いた場合、attrの中身にディレクティブがあってもコンパイラには見えないので注意が必要です。

テンプレートディレクティブの中には、独自の値を設定できるものもあります。例えば、

  • <X client:load /> → 値を設定する必要がありません
  • <X class:list={['some-css-class']} /> → 配列を値として渡します。

なお、テンプレートディレクティブはコンポーネントの最終的なHTML出力には含まれません。あくまでAstroのビルド時に使われる特別な指示といえるでしょう。

class:list={...} は、複数のクラス値を配列で受け取り、それを一つのクラス文字列に変換します。この機能は、@lukeedの人気ライブラリ clsx を使って実現しています。

class:list で使える値の種類は以下の通りです。

  • 文字列:そのまま要素のクラスとして追加されます
  • オブジェクト:値が真のキーが要素のクラスとして追加されます
  • 配列:中身を展開して処理します
  • false, null, undefined:無視されます
<!-- This -->
<span class:list={[ 'hello goodbye', { world: true }, [ 'friend' ] ]} />
<!-- Becomes -->
<span class="hello goodbye world friend"></span>

set:html={string} は、HTML文字列を要素の中身として挿入します。これは el.innerHTML を使うのと似た動作をします。

注意:Astroは自動的にこの値をエスケープしません! 必ず信頼できる値を使うか、テンプレートに渡す前に手動でエスケープしてください。これを怠ると、クロスサイトスクリプティング(XSS)攻撃の危険性があります。

---
const rawHTMLString = "Hello <strong>World</strong>"
---
<h1>{rawHTMLString}</h1>
<!-- Output: <h1>Hello &lt;strong&gt;World&lt;/strong&gt;</h1> -->
<h1 set:html={rawHTMLString} />
<!-- Output: <h1>Hello <strong>World</strong></h1> -->

また、set:html<Fragment> でも使えるので、余分なラッパー要素を追加せずにHTMLを挿入できます。これはCMSからHTMLを取得する場合などに特に便利です。

---
const cmsContent = await fetchHTMLFromMyCMS();
---
<Fragment set:html={cmsContent}>

set:html={Promise<string>} を使うと、PromiseでラップされたHTML文字列を要素に挿入できます。

これは、データベースなどに保存されている外部のHTMLを挿入する際に役立ちます。

---
import api from '../db/api.js';
---
<article set:html={api.getArticle(Astro.props.id)}></article>

set:html={Promise<Response>} を使うと、Response オブジェクトの内容を要素に挿入できます。

これは主に fetch() を使う場合に便利です。例えば、以前の静的サイトジェネレーターで作成した古い記事を取得する際などに使えます。

<article set:html={fetch('http://example/old-posts/making-soup.html')}></article>

set:html はどんなタグでも使えますし、必ずしもHTMLを含める必要はありません。例えば、ページに JSON-LD スキーマを追加したい場合、<script> タグ内で JSON.stringify() と組み合わせて使うこともできます。

<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org/",
"@type": "Person",
name: "Houston",
hasOccupation: {
"@type": "Occupation",
name: "Astronaut"
}
})}/>
Astroコンポーネントでのクライアントサイドスクリプト (EN)の動作についてはこちらをご覧ください。

define:vars={...} を使うと、コンポーネントのフロントマターからクライアントの <script><style> タグに、サーバーサイドの変数を渡せます。JSON形式にできるフロントマター変数なら何でも使えます。Astro.props を通じてコンポーネントに渡された props も含みます。値は JSON.stringify() でシリアライズされます。

---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
const message = "Astroは素晴らしい!";
---
<style define:vars={{ textColor: foregroundColor, backgroundColor }}>
h1 {
background-color: var(--backgroundColor);
color: var(--textColor);
}
</style>
<script define:vars={{ message }}>
alert(message);
</script>

is:raw は、Astroコンパイラにその要素の中身をテキストとして扱うよう指示します。これにより、その要素内ではAstroの特殊なテンプレート構文がすべて無視されます。

例えば、テキストをHTMLに変換するカスタムのKatexコンポーネントがある場合、ユーザーは以下のように使えます。

---
import Katex from '../components/Katex.astro';
---
<Katex is:raw>ここには{構文}の衝突があります</Katex>
貢献する コミュニティ スポンサー