LoginSignup
0
0

Svelte チュートリアル学習ノート その1

Last updated at Posted at 2024-05-18

動機

現在、日本語学習者向けの漢字学習アプリを開発しています。
バックエンドに Bun & Elysia を採用することは決定しているので、
フロントエンドはできれば React, Vue, Svelte あたりから選びたいと考えています。
本記事は Svelte を触って何かやってみるための準備の記録です。

教材

Svelte チュートリアル
本記事は Part 1: Basic Svelte の前半部分 (Introduction, Reactivity, Props) のノートです。

Svelteを使うと何がうれしいのか

  • コンポーネントベースでWebアプリが構築できる
  • JavaScriptにコンパイルされるため、オーバーヘッドがない
  • 1つのコンポーネント (.svelte ファイル) にHTML, CSS, JavaScript を記述でき、自己完結させやすい

基本的な書き方

{} を使ってJSコードを埋め込む

JSX/TSXと同様です。

App.svelte
<script>
	let src = '/image.gif';
	let name = 'Rick Astley';
</script>

<img src={src} alt="{name} dances." />
<!-- <img src="/image.gif" alt="Rick Astley dances." /> -->

なお、src={src} のように属性名と変数名が同じ場合、シンプルに {src} とも書けます。


import 文でコンポーネントを読み込む

App.svelte
<script>
	import AnotherComponent from './AnotherComponent.svelte';
</script>

{@html ...} で文字列をHTMLとしてレンダリングする

App.svelte
<script>
	let string = `this string contains some <strong>HTML!!!</strong>`;
</script>

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

this string contains some HTML!!!

Reactivity システム (DOM を更新する)

イベントハンドラを定義する

App.svelte
<script>
	let count = 0;

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

<button on:click={increment}>
	Clicked {count}
	{count === 1 ? 'time' : 'times'}
</button>

on:click={...} 部分がイベントハンドラにあたります。
このケースでは、ボタンをクリックしたときに increment() が発火し、count が更新され再レンダリングされます。


$: を使って、関連するDOMを更新させる (Reactive declaration: リアクティブ宣言)

App.svelte
<script>
	let count = 0;

	$: doubled = count * 2;

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

<button on:click={increment}>
	Clicked {count}
	{count === 1 ? 'time' : 'times'}
</button>

<p>{count} doubled is {doubled}.</p>

$: doubled = count * 2; という宣言をすることで、count が更新された時に、 doubled の再代入と再レンダリングが行われます。

doubled の再代入」と書きましたが、より正しくは、 $: 以降の処理の再実行 (re-action) が行われるので、値の設定だけでなく、関数の実行もできます。制御構文も書けます。

$: console.log(`Someone seems to have pressed the button.`);
$: if (age === 18) {
	alert('Congratulations! You are now ready to vote.');
}

リアクティビティは代入によってトリガーされますが、push(), pop() などのいわゆる破壊的メソッドによってはトリガーされません
愚直ですが、自身を再代入することでトリガーできます。

function addNumber() {
	numbers.push(numbers.length + 1);
	numbers = numbers;  // この文がないと、push だけでは numbers に対するリアクションが発火しない
}

export で子コンポーネントへのデータ受け渡しを行う (いわゆる props)

Child.svelte
<script>
	export let place;
</script>

<p>Stairway to {place}</p>
App.svelte
<script>
	import Nested from './Nested.svelte';
	let place = "Heaven"
</script>

<Nested place={place} />

結果

Stairway to Heaven

props のデフォルト値を設定する

値を代入しておけばよいです。

Child.svelte
<script>
	export let place = 'Paradise';
</script>

<p>Stairway to {place}</p>
App.svelte
<script>
	import Nested from './Nested.svelte';
	let place = "Heaven"
</script>

<Nested />

結果

Stairway to Paradise

props の受け渡しにはスプレッド構文が使える

さもありなん、というところです。

NovelInfo.svelte
<script>
	export let title;
	export let author;
	export let nationality;
	export let publishedYear;
</script>

<p>
	"{title}" is a novel by {nationality} author {author}, first published in {publishedYear}.
</p>

App.svelte
<script>
	import NovelInfo from './NovelInfo.svelte';

	const book = {
		title: 'Confessions of a Mask',
		author: 'Yukio Mishima',
		nationality: 'Japanese',
		publishedYear: '1949'
	};
</script>

<PackageInfo {...book} />

結果

"Confessions of a Mask" is a novel by Japanese author Yukio Mishima, first published in 1949.

雑感

useStateuseEffect などの hooks ががっちりと用意されている React.js と比べて、学習・実装コストとも低いと感じました。
この調子でチュートリアルを進めていきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0