初めてのスクリプトをブラウザに送信する
クライアントサイドのインタラクションを必要とするような、モバイルの画面サイズでナビゲーションメニューを開閉するボタンを追加しましょう!
ここで学ぶことは...
- メニューコンポーネントを作成する
- サイト訪問者がナビゲーションメニューを開閉できるように
<script>を書く - JavaScriptを
.jsファイルに移動する
メニューコンポーネントを作成する
モバイルメニューを開閉する<Menu />コンポーネントを作成します。
src/components/にMenu.astroという名前のファイルを作成します。以下のコードをコンポーネントにコピーします。これは、モバイルデバイスでナビゲーションリンクを開閉するボタンを作成します。(あとで
global.cssに新しいCSSスタイルを追加します。)--- --- <button aria-expanded="false" aria-controls="main-menu" class="menu"> Menu </button>Header.astroの<Navigation />コンポーネントの直前に、新しい<Menu />コンポーネントを配置します。コードを表示
--- import Menu from './Menu.astro'; import Navigation from './Navigation.astro'; --- <header> <nav> <Menu /> <Navigation /> </nav> </header>レスポンシブなスタイルを含む以下のメニューコンポーネント用スタイルを追加します。
/* ナビゲーションのスタイル */ .menu { background-color: #0d0950; border: none; color: #fff; font-size: 1.2rem; font-weight: bold; padding: 5px 10px; } .nav-links { width: 100%; display: none; margin: 0; } .nav-links a { display: block; text-align: center; padding: 10px 0; text-decoration: none; font-size: 1.2rem; font-weight: bold; text-transform: uppercase; color: #0d0950; } .nav-links a:hover, .nav-links a:focus{ background-color: #ff9776; } :has(.menu[aria-expanded="true"]) .nav-links { display: unset; } @media screen and (min-width: 636px) { .nav-links { margin-left: 5em; display: block; position: static; width: auto; background: none; } .nav-links a { display: inline-block; padding: 15px 20px; } .menu { display: none; } }
初めてのスクリプトタグを書く
ヘッダーはまだインタラクティブではありません。メニューへのクリックに応じてナビゲーションリンクを表示したり非表示にしたりするように、ユーザーの入力に応答することができないからです。
<script>タグを追加すると、クライアントサイドのJavaScriptがユーザーのイベントを「待ち受け(Listen)」、それに応答します。
index.astroの</body>閉じタグの直前に、Astro組み込みのTypeScriptサポートを利用して以下の<script>タグを追加します。<Footer /> <script> const menu = document.querySelector('.menu'); menu?.addEventListener('click', () => { const isExpanded = menu.getAttribute('aria-expanded') === 'true'; menu.setAttribute('aria-expanded', `${!isExpanded}`); }); </script> </body>ブラウザのプレビューを複数のサイズで開き、このページのナビゲーションメニューがスクリーンサイズに対してレスポンシブであり、またユーザーの入力に反応することを確認します。
.jsファイルをインポートする
各ページにJavaScriptを直接書く代わりに、<script>タグの内容をプロジェクト内の.jsファイルに移動しましょう。
(新しく
/scripts/フォルダを作成した上で)src/scripts/menu.jsを作成し、JavaScriptをそこに移動します。const menu = document.querySelector('.menu'); menu?.addEventListener('click', () => { const isExpanded = menu.getAttribute('aria-expanded') === 'true'; menu.setAttribute('aria-expanded', `${!isExpanded}`); });index.astroの<script>タグの内容を以下のファイルインポートに置き換えます。<Footer /> <script> const menu = document.querySelector('.menu'); menu?.addEventListener('click', () => { const isExpanded = menu.getAttribute('aria-expanded') === 'true'; menu.setAttribute('aria-expanded', `${!isExpanded}`); }); import "../scripts/menu.js"; </script> </body>ブラウザのプレビューを再度小さいサイズで開き、メニューがナビゲーションリンクを開閉することを確認します。
他の
about.astroとblog.astroの2ページにも同じ<script>とインポートを追加し、両ページにレスポンシブでインタラクティブなヘッダーがあることを確認します。<Footer /> <script> import "../scripts/menu.js"; </script> </body>
:::note[要点]これまでにも、サイトの一部を作成するためにJavaScriptを使用してきました。
- ページタイトルと見出しの動的な定義
- 概要ページでのスキルリストのマッピング
- HTML要素の条件に応じた表示
これらの命令はすべてビルド時に実行され、サイトの静的HTMLを作成したあと、コードは「捨てられます」。
<script>タグ内のJavaScriptはブラウザに送信され、ユーザーの操作に応じてページの更新や入力の切り替えなどを実行します。:::
確認テスト
Astroは、コンポーネントのフロントマターに書かれたJavaScriptをいつ実行しますか?
Astroでは任意でJavaScriptをブラウザに送信できますが、その目的は何ですか?
クライアントサイドのJavaScriptがユーザーのブラウザに送信されるのは、それがどこに書かれた・インポートされたときですか?