🐌

Svelteなんもわからん

2024/10/28に公開

小一時間LEARN.SVELTE.DEV.Part1やったが多分なんもわかっていない。

SvelteKitもやったけどなんもわからんよ。(微笑)

概要

<script><script/>, htmlタグを含む単一の.svelteファイルを作成する。

各.svelteファイルはコンポーネントを表している。

それらは単一のjsファイルにコンパイルされる。
ツリーシェイキングによりライブラリサイズも小さくするので、オーバーヘッドが小さく、速い。
ツリーシェイキングついて)別ライブラリだが、https://blog.theodo.com/2021/04/library-tree-shaking/

アプリを作るためにはSvelteKitを使う。よーしアプリ作るぞ。

get started

https://svelte.jp/

のチュートリアルを進めていく。

コンポーネントとは

.svelteファイルはコンポーネントを定義する。
大文字から始めて、そのコンポーネントのタグを置く。

<Component />

コンポーネントは

  • 描画されることができ
  • 内部状態をもち(props / reactivity)
  • 操作に反応できる(イベントハンドリング)

reactivity(反応性)システム

コンポーネントは状態(props)を持つのですが、その状態が変化したときすることが多々あるかと思います。
その時使えるのが$。

let a = 1;
$: a_plus_one = a + 1;

これで変数を自動更新できる。
逆に更新したくないときはconstを使う。

reactivityは任意のコードを実行できる。長いコードにしてもよい。

let a = 1;
$: {
    a_plus_one = a + 1;
}

リストやオブジェクトの変数の場合、そのメソッドを読んだ結果中身が変わってもreactivityはトリガーされない。これはほかのフレームワークと同じ。

手動トリガーにはなんと代入を使う。

a = a;

props

コンポーネントの状態を外から変更するとき宣言する。

export let a = 1;

で宣言し、初期化時に値を渡す。

<Component a=2 />
<Component />

2番目の例ではデフォルト値に設定した1が使われる。

Logic

if, each(, await)

だけ覚えればいい、つまりifとforだけで、テンプレート系の言語がforをeachと書くのは30年前のphpからそう

awaitがあるのが現代JavaScriptっぽいと思う。

Events

コンポーネントにオリジナルのイベント作れる。

<script>
import { createEventDispatcher } from 'svelte';
</script>
...

<button on:originalevent />

イベントバブリングやフォワーディングが可視化されてなくてちょっとつらいでござる。

Bindings

子から親の変数を書き換えるために、script内の変数と、コンポーネントをバインドする
具体的にはbind:をつけるだけだが、だんだん何が起こっているのか頭で把握しきれなくなってきた。

子とか親とかいうから抽象的過ぎる。
具体的には、コンポーネント内のインプットを変更したときに、コンポーネントの状態を変えたいということ。

Lifecycle

基本的にメモリリークを防ぐために、onDestroyで何を書けばいいか学習しておきましょう。という感じ。

onMount(fstart, fend)
beforeUpdate(() => {})
afterUpdate(() => {})
await tick();

tickだけは例外で、イベント発動タイミングをちょっとずらすというよくわからない動作をする。
バグっているときawait tickすれば治る。(???)

Stores

最後にstoreといえばデータベースなど永続化手段を指すと思うのだが・・・
SvelteのStoresは
「subscribeメソッドを正しく実装しているオブジェクト」
というわけわからん概念。

readableは何らかの値を生成して返すクラスに見える。subscribeすると値が変化したときにイベントみたいなものが飛ぶ。

writableはもっとよくわからん。set(value), update(lambda)というメソッドを追加で持っている。

subscribeは$でも書ける。これをauto-subscribeという。

おいていかれた気がする。どゆこと

そこでよく読み返してみると、どうやらStoresというのはコンポーネントの外にある、グローバル変数のようなもののようだ。

グローバル変数が更新されたとき、それを知ることは出来ない。だから、関係者コンポーネントだけがその変数をsubscribeして、更新を通知してもらうのだ。

すなわち、Stores(のwritable)は、更新通知付きグローバル変数と考えてよいだろう。そのグローバル変数にはset(value)で書き込めばいいということ。

subscribeのみでよいと考えると、readableで十分のような考え方になるのだろう。

auto-subscribe

そう考えると、$countのような、$で始まるauto-subscribeな変数は、グローバル変数への参照のようなものと考えることができる。

これはsubscribeとonDestroyを組み合わせたものに対するシュガーシンタックスとのことだが、$以外を使うときっとバグるからやめておこう。

store-binding / derive

グローバル変数が2つあって中身を連動させたい場合はstoresに対してもbindが出来る。

https://learn.svelte.jp/tutorial/store-bindings

この例では

import { name, greeting } from './stores.js';

として、stores.jsの中でderivedを使ってnameとgreetingを関連付けている。

export const greeting = derived(name, ($name) => `Hello ${$name}!`);

感想

なんか現代のフロントエンドのプログラミングってワイヤーで要所を繋ぐみたいですね。(シンセサイザーのイメージ)

一旦終わり

これで基本を学習したので、次はSvelteの高度なテクニックを学ぶ時間です。
まずはmotionから始めましょう。

とか出てきたんだけど。
いやいや、こりゃあと3周しないとなんもわからんな・・・

Discussion