AstroのComponent Script(---で囲われたScript)と、クライアントサイドのScript(<script>
タグを使うやつ)で同じデータを使いたい場合の小ネタを紹介します。
Component ScriptとクライアントサイドのScriptはスコープが違うというか、Component Scriptはユーザーのブラウザ側で実行されないので、それぞれで変数が共有されません。。例えば、以下のコードではdefaultTodoTasks変数はクライアントサイドのScriptから参照できません。
---
import MySiteLayout from "../layouts/MySiteLayout.astro";
// Component Script (JavaScript)
const defaultTodoTasks = [
{
slug: "gym",
title: "ジム",
completed: false,
},
{
slug: "walking",
title: "散歩",
completed: false,
}
];
---
<MySiteLayout title="Home Page">
<ul>
{defaultTodoTasks.map(task => (
<li>
{task.title}: {task.completed ? '完了' : '未完了'}
</li>
))}
</ul>
<script>
console.log(defaultTodoTasks.length) // Uncaught ReferenceError: defaultTodoTasks is not defined
</script>
</MySiteLayout>
そこで、データをファイルとして保存し、exportとimportを使うことで両方のスクリプトから同一のデータを扱うことができます。
まず、defaultTodoTasks.jsという名前のファイルを作成し、そこでdefaultTodoTasks変数を定義してexportします。
src/data/defaultTodoTasks.js
export const defaultTodoTasks = [
{
slug: "gym",
title: "ジム",
completed: false,
},
{
slug: "walking",
title: "散歩",
completed: false,
}
];
次に、Component ScriptとクライアントサイドのScriptの両方でdefaultTodoTasksをimportします。
src/pages/index.astro
---
// Component Script (JavaScript)
import MySiteLayout from "../layouts/MySiteLayout.astro";
import { defaultTodoTasks } from '../data/defaultTodoTasks.js';
---
<MySiteLayout title="Home Page">
<ul>
{defaultTodoTasks.map(task => (
<li>
{task.title}: {task.completed ? '完了' : '未完了'}
</li>
))}
</ul>
<script>
import { defaultTodoTasks } from '../data/defaultTodoTasks.js';
console.log(defaultTodoTasks.length) // output: 2
</script>
</MySiteLayout>
defaultTodoTasks.jsファイル内でdefaultTodoTasksを定義することで、Component ScriptとクライアントサイドスクリプトからdefaultTodoTasksにアクセスができるようになりました!