Svelteコンポーネントの基本
以下では、生成したSvelteKitプロジェクトをもとに、Svelteコンポーネントを利用してWebページを実装する方法を説明します。
Webページ全体に対応するコンポーネントのファイルは、表2、No.2に示したsrc/routes/+page.svelteファイルです。このファイルに実装を加えた図4のサンプルで、Svelteコンポーネントの基本的な実装方法を説明します。前回記事でも紹介した、ボタンのクリックでカウントが増加するサンプルです。
図4の+page.svelteファイルを、リスト2に示します。
<script lang="ts"> // 実装 ...(1)
let count: number = 0; // ...(1a)
const increment = () => { // ...(1b)
count += 1;
};
</script>
<!-- マークアップ ...(2)-->
<h1>コンポーネントのサンプル</h1>
<button on:click={increment}> <!--(2a)-->
count is {count} <!--(2b)-->
</button>
<style> /* スタイル指定 ...(3)*/
button { font-size: 20pt; }
</style>
Svelteコンポーネント(*.svelteファイル)は、<script>タグ内に記述する実装(1)、表示内容のマークアップ(2)、<style>タグ内に記述するスタイル指定(3)からなります。これらの記述はいずれも任意で、どれかの要素を含まないこともできます。
<script>タグの属性lang="ts"は、記述言語がTypeScriptであることを表します。実装はTypeScriptの標準的な記法で行えます。ここでは(1a)でカウントの変数countを0で初期化し、(1b)ではcountを1増やすincrement関数を実装しています。
マークアップは(Svelte独自の記述を含んだ)HTMLで行います。(2a)のon:click={increment}は、ボタンのクリックイベント発生時に(1b)のincrement関数を実行することを表します。このようにon:<イベント名>={<処理>}でイベント発生時の処理を指定できます。また(2b)の通り{count}と、変数名を中括弧で囲って記述すると、その変数の内容をWebページに表示できます。
<style>タグのスタイル指定は、標準的なCSSで記述します。ここではbuttonタグのスタイルを指定しています。
マークアップの条件分岐と繰り返し
マークアップでは条件分岐や繰り返しの指定ができます。図5のサンプルでは、カウント値の条件分岐(5未満、5以上、10以上)による表示の出しわけと、カウント値配列の繰り返しによる表示を行います。
条件分岐の記述はリスト3の通りです。(1)の#if、(2)の:else if、(3)の:elseで条件を指定し、条件指定の最後は(4)の/ifで閉じます。
{#if count >= 10} <!--(1)-->
<p>countは10以上</p>
{:else if count >= 5} <!--(2)-->
<p>countは5以上</p>
{:else} <!--(3)-->
<p>countは5未満</p>
{/if} <!--(4)-->
繰り返しの記述はリスト4の通りです。(1)の#eachで繰り返しを指定します。countArray as itemは、countArray配列の各要素をitemとして参照する意味で、itemは(2)の記述で画面に表示させます。繰り返し範囲の最後は(3)の/eachで閉じます。なおcountArray配列は、カウンターが増えるごとにその値が末尾に追加される配列です(実装の詳細はサンプルコードを参照してください)。
<div class="count-array">
{#each countArray as item} <!--(1)-->
<span>{item}</span> <!--(2)-->
{/each} <!--(3)-->
</div>
複数コンポーネントの利用
これまでのサンプルでは1つのコンポーネント(+page.svelte)でWebページ全体を記述しましたが、Webページの内容を複数コンポーネントで記述することもできます。図6のサンプルでは、1つのWebページ内に、iPhone、Android、Chromebookに対応した3つの子コンポーネント(*.svelteファイル)を表示しています。各コンポーネントにはメーカー、機種、在庫数が表示され、在庫追加ボタンをクリックすると在庫数が増加します。
iPhoneに対応する子コンポーネント(iPhone.svelteファイル)はリスト5の通りです(Android、Chromebookに対応する子コンポーネントも実装内容はほぼ同一です)。
<script lang="ts">
// プロパティ ...(1)
export let vendor = 'Apple';
export let model = '';
export let count = 0;
</script>
<!-- プロパティ内容を表示 ...(2)-->
<div class="container">
<div>【iPhone】</div>
<div>メーカー:{vendor}</div>
<div>機種:{model}</div>
<div>在庫数:{count}</div>
</div>
(略:<style>要素)
(1)の通りexport letと記述した変数はコンポーネントのプロパティとなり、外部から設定できるようになります。このプロパティは(2)のマークアップ部で参照して画面に表示されるようにします。
一方、子コンポーネントを表示する親コンポーネント側の実装はリスト6となります。
<script lang="ts">
// 子コンポーネントをインポート ...(1)
import IPhone from './iPhone.svelte';
import Android from './Android.svelte';
import Chromebook from './Chromebook.svelte';
// 在庫数 ...(2)
let iPhoneCount = 0;
let androidCount = 0;
let chromebookCount = 0;
</script>
<!-- 在庫追加ボタン ...(3)-->
<button on:click={() => { iPhoneCount += 1; }}>iPhone在庫追加</button>
<button on:click={() => { androidCount += 1; }}>Android在庫追加</button>
<button on:click={() => { chromebookCount += 1; }}>Chromebook在庫追加</button>
<!-- 子コンポーネント ...(4)-->
<IPhone model="iPhone 15"
count={iPhoneCount}></IPhone> <!-- vendor未指定 ...(4a)-->
<Android vendor="OPPO" model="Reno11 A"
count={androidCount}></Android>
<Chromebook vendor="Lenovo" model="IdeaPad Slim 3"
count={chromebookCount}></Chromebook>
<script>部の(1)で子コンポーネントをインポートします。コンポーネント名は先頭が大文字になる決まりなので、iPhoneについては「IPhone」というコンポーネント名にしています。マークアップ部の(4)では各コンポーネントにプロパティを指定して記述します。(4a)でvendorが未指定になっていますが、この場合はリスト5(1)で定義したvendorの初期値「Apple」がそのまま利用されます。
なお、コンポーネントのプロパティには固定値ではなく変数を指定することもできます。リスト6では(2)で定義した在庫数の変数を、(4)で各コンポーネントのcountプロパティに指定しています。(3)はクリック時に在庫数を増やすボタンの実装です。
[補足]スタイル指定はそのコンポーネント内のみに適用される
Svelteコンポーネントのスタイル指定はコンポーネント内のみに適用されます。図6のサンプルでは、iPhone、Android、Chromebookの子コンポーネントで同一のクラス名containerを利用して、異なるスタイルが個別に指定されていますが、各コンポーネントでスタイルが相互干渉することなく表示されます。
