👑

Svelte再入門

に公開

ここ最近ReactやVueしか触ってなくて、Svelteで遊びたくなってつい

Svelteとは?

svelte: 形容詞 魅力的でスリム、優雅でスタイリッシュ

Svelte はコンパイラを使用する UI フレームワークで、息を呑むほど簡潔にコンポーネントを記述でき、 ブラウザで最小限の動作となるようにしてくれます。開発者には既知の言語である HTML、CSS、JavaScript を使うことができます。 これは、web 開発へのラブレターです。

私たちだけでなく、常に開発者たちからも、Svelte は使用する上で最もエキサイティングなフレームワークとしてランク付けされています。

https://svelte.jp

要するに

React, Vue相当のフロントエンドフレームワーク

概要

App.svelte
<script lang="ts">
  const message = "click me"
  function greet() {
    alert('Welcome to Svelte!');
  }
</script>

<button onclick={greet}>{message}</button>

<style>
  button {
    font-size: 2em;
  }
</style>

getting started

Viteで環境構築

npm create vite@latest my-app -- --template svelte-ts

Runeとは

$ から始まるSvelte独自の組み込み機能のこと

構文 説明 他FWでいうところの
$state 状態管理 useState/useState
$derived 派生状態 useMemo/computed
$effect 副作用 useEffect/watchEffect
$props コンポーネントへの入力 props
$bindable 双方向バインディング v-model
$host ホスト要素の参照 ref

$state

状態管理

<script>
	const FIZZ = "Fizz";
	const BUZZ = "Buzz";
	const FIZZ_BUZZ = FIZZ + BUZZ

	let count = $state(0);

	function increment() {
		count++;
	}
</script>

<button onclick={increment}>
	Clicked {count}
</button>
<div>
	{#if count % 3 === 0 && count % 5 === 0}
		<div>{FIZZ_BUZZ}</div>
	{:else if count % 3 === 0}
	  <div>{FIZZ}</div>
	{:else if count % 5 === 0}
	  <div>{FIZZ_BUZZ}</div>
	{:else}
	  <div>-</div>
	{/if}
</div>

$derived

stateを利用するstate

<script>
	let numbers = $state([1, 2, 3, 4]);
	let total = $derived(numbers.reduce((t,n) => t+n, 0));
	function addNumber() {
		numbers.push(numbers.length + 1);
	}
</script>

<p>{numbers.join(' + ')} = {total}</p>

<button onclick={addNumber}>
	Add a number
</button>

$inspect

stateを監視し自動記録する

<script>
	let numbers = $state([1, 2, 3, 4]);
	let total = $derived(numbers.reduce((t, n) => t + n, 0));

	function addNumber() {
		numbers.push(numbers.length + 1);
	}
	$inspect(numbers).with(console.trace);
</script>

<p>{numbers.join(' + ')} = {total}</p>

<button onclick={addNumber}>
	Add a number
</button>

ディレクティブ

@ から始まる構文のこと

@html

文字列をテキストではなく、HTMLとして読み込む

<script>
	let html = `this string has <strong>HTML!!!</strong>`;
</script>

<p>{@html html}</p>

構文

条件分岐 if-elseif-else

<div>
    {#if count > 10}
    	<p>{count} is greater than 10</p>
    {:else if count < 5}
    	<p>{count} is less than 5</p>
    {:else}
    	<p>{count} is between 5 and 10</p>
    {/if}
</div>

繰り返し for-each

<script lang="ts">
	const numberArray = [0,1,2,3,4,5];
</script>

<div>
	{#each numberArray as num}
		<div>{num} item</div>
	{/each}
</div>

DOMイベント

on<name> 関数を利用する

  • onclick ⇒ クリックイベント
  • onpointermove ⇒ マウスポインタ移動イベント

バインド

<script>
	let name = $state('world');
</script>

<input bind:value={name} />

<h1>Hello {name}!</h1>

スニペット

別のファイルに抽出することなく、
コンポーネント内のコンテンツを再利用できる機能
これが好き

<table>
	<thead>
		<tr>
			<th>emoji</th>
			<th>description</th>
			<th>unicode escape sequence</th>
			<th>html entity</th>
		</tr>
	</thead>

	<tbody>
		{#snippet monkey(emoji, description)}
			<tr>
				<td>{emoji}</td>
				<td>{description}</td>
				<td>\u{emoji.charCodeAt(0).toString(16)}\u{emoji.charCodeAt(1).toString(16)}</td>
				<td>&amp#{emoji.codePointAt(0)}</td>
			</tr>
		{/snippet}
		{@render monkey('🙈', 'see no evil')}
		{@render monkey('🙉', 'hear no evil')}
		{@render monkey('🙊', 'speak no evil')}
	</tbody>
</table>

所感

React, Vueだと外部ライブラリに依存する部分が内包されててイイね!

Discussion