Svelteを素振りしてみた

Svelteを素振りしてみた フロントエンド定例 2023/1/6

tanifumiya|2023年01月06日
フロントエンド

こんにちは、フロントエンドチームの 谷(@high_g_engineer)です。
今週のフロントエンド定例の内容を記載します。

フロントエンド定例について、以前の記事(ランサーズのフロントエンドチームが取り組んでいること)でお伝えしたのですが、毎週金曜日に開催しており、実際の業務で取り組んでいることや気になった技術情報等をシェアしあう会になっています。

以下、今週の内容です。

Svelte(スベルト)とは

React, Vueと同じ様に宣言的に記述できるフロントエンドフレームワークです。
React, Vueと少し性質が異なるのは、仮想DOMを利用していない点です。

https://svelte.jp/

環境設定

古い環境構築

npx degit sveltejs/template プロジェクト名

新しい環境構築(Vite)

npm init vite@latest

Svelte選択

コード

基本

コード全体はVueに似ています。
コンポーネントの扱いは、React, Vueと同じ感覚で、
html変数などを埋め込む場合は、Reactと同じ様に、 {} を利用します。

<script>
import Counter from './components/Counter.svelte'
let name = 'test'
</script>

<main>
  <h1 class="active">Vite + Svelte</h1>
  <p>{name}</p>
  <div class="card">
    <Counter />
  </div>
</main>

<style>
.active {
  font-size: 3em;
  font-weight: 700;
}
</style>

HTML

if

{#if} 〜 {/if} で記述を行います。
else if や else には、:をつけることで記述可能です。

<button on:click={increment}>
  count is {count}
  double is {double}

  {#if count<5}
  countは5未満です
  {:else if count >= 5 && count < 10}
  countは5以上10未満です
  {:else}
  countはそれ以外です
  {/if}
</button>

ループ

html内のループを記述する場合です。

{#each users as user}
<p>{user}</p>
{/each}

await

promiseの処理を利用した記述もそのままhtmlに記述可能です。

{#await promise}
<p>waiting for the promise to resolve...</p>
{:then value}
<p>The value is {value}</p>
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}

CSS

基本

<style></style> の中にスタイルを記述します。
スタイルは通常のCSSと同じ記述になります。
Scoped CSSなので、コンポーネント内のみで記述したスタイルが適用されます。

<h2 class="active">Styling</h2>

<style>
.active {
  font-size: 3em;
  font-weight: 700;
}
</style>

グローバルなスタイル

グローバルなスタイルに影響を与える記述は、:global を利用します。

:global(対象セレクタ) {}

変数名によるスタイル

jsで定義した変数に格納された文字列をクラス名として利用したい場合は、
下記のように class={変数名} で利用できます。

<script>
let emphasis = 'active';
</script>

<h2 class={emphasis}>Styling</h2>

<style>
.active {
  font-size: 3em;
  font-weight: 700;
}
</style>

Svelteのコンポーネント仕様

props

propsを利用する場合、子コンポーネント側で export let props名 と記述します。

親側

<Text name="test1" />

子側

<script>
export let name
</script>

<p class="text">{name}</p>

slot

下記のような記述で、子コンポーネントに囲われた範囲をそのまま渡したい場合、slotを利用します。

<component>aaaa</component>

子コンポーネント側で以下の様に記述すれば、親コンポーネント側記述した値が埋め込まれます。

<div class="box">
  <slot></slot>
</div>

また、script部で、$$slots と記述することで、script側でもslotの値を利用可能です。

ステート

ReactのuseStateの様な記述はなく、シンプルに変数を利用します。
変数同士で影響しあう記述をしたい場合は、 $: で変数を定義します。

<script>
let count = 0
const increment = () => {
  count += 1
}
$: double = count * 2
</script>

<button on:click={increment}>
  count is {count}
  double is {double}
</button>

$: にはconsole.logも書けるし、複数行も書けます。

$: { console.log(`現在のcountの値は${count}です`); console.log('複数行も設定できます。'); }

bind

変数宣言した値をそのままinputタグのvalueとして記述したい場合、
下記の様に bind:value={変数} と記述します。

<script>
let bindName = 'aaa'
</script>

<input type="text" bind:value={bindName} />

ライフサイクルフック

  • コンポーネントがマウントされた際に、onMountが実行されます。
  • コンポーネントの更新が行われると、beforeUpdateとafterUpdateが実行されます。
  • アンマウントする際にonDestroyが実行されます。
import { beforeUpdate, onMount, onDestroy, afterUpdate } from 'svelte';

beforeUpdate(() => {
  console.log('beforeUpdate execute');
});
onMount(() => {
  console.log('onMount execute');
});
afterUpdate(() => {
  console.log('afterUpdate execute');
});
onDestroy(() => {
  console.log('onDestroy execute');
});

グローバルステート

Reactには、グローバルステートライブラリとして、Redux, Recoil, Jotai, Zustand等様々なライブラリがあり、VueにもVuex以外にPiniaというライブラリが存在しています。

Svelteには、そういったライブラリはなく、デフォルトでStoreが用意されています。
シンプルイズベスト!

Storeに関しては、深堀りができていない為、またの機会に素振りしようと思います。

参考

はじめてSvelteを利用する人のためのSvelte入門

 

ランサーズでは、フロントエンドエンジニアを随時募集しておりますので、まずはお話でもという方はご連絡くださいませ!

フロントエンドエンジニア(本社)の採用情報 | ランサーズ株式

前回の定例内容はこちらから確認可能ですのでご興味いただければ下記のリンクから閲覧いただければと思います。

https://engineer.blog.lancers.jp/?s=フロントエンド定例