より軽く、より速く-Svelteフレームワークのガイド
公開: 2022-03-11Webアプリケーションは日々人気が高まっています。 それらは、その単純さ、速度、およびクロスプラットフォームの可用性のために人々が選択する成長している世界です。 シングルページアプリケーション(SPA)は、このプロセスに大きな役割を果たしています。 Angular、Vue.js、Reactなどのフレームワークは、開発者がコードをサポート可能で拡張可能な状態にして、短期間で最高のユーザーエクスペリエンスを提供するのに役立ちます。 これらのツールは、この分野で長い間最も人気があり、新しく作成されたパッケージに比べて多くの利点があります。 それはSPAの世界では寡占のように感じられました。 ただし、この市場をターゲットとする前向きな開発者のグループは、真剣な競争相手であるSvelteと一緒に参入する可能性があります。
Svelteは、ユーザーインターフェイスを構築するための新しいアプローチです。 一般的なログインフォームを作成して、何がこれほど新鮮なのかを調べてみましょう。
建築
Svelteは、他のどのライブラリよりも高速になるように設計されています。 これは、仮想DOMを構築するためのフレームワークをロードするステップをシフトすることによって達成されます。 実行プロセス中にツールを使用する代わりに、ビルド段階でバニラJSにコンパイルされるため、アプリケーションを起動するために依存関係は必要ありません。
Svelte | その他のSPAライブラリ(React、Vue.js、Angularなど) |
---|---|
1.Webサイトを開きます | 1.Webサイトを開きます |
上記の表は、Svelteがスタートアップパフォーマンスで絶対的な勝者である理由を示しています。 これは、いかなる種類の最適化によっても得られませんが、サイドコンパイラの代わりに利用可能なブラウザのJavaScriptコンパイラを使用することによって得られます。
インストール
Svelteのインストールは非常に簡単で、非常に快適に使用できます。 最初のステップは、プロジェクトのテンプレートをダウンロードすることです。
npx degit sveltejs/template svelte-login-form
上記のコマンドを完了すると、Svelteプロジェクトテンプレートが作成されます。 今のところ空で、必要なNPMパッケージはまだインストールされていません。 それを修正しましょう。
cd svelte-login-form npm install
これで、次のコマンドを使用してアプリケーションを起動する準備が整いました。
npm run dev
構造
Svelteコンポーネントには、次のセクションが含まれている場合があります。
- 脚本
- スタイル
- テンプレート
src/App.svelte
ファイルの例を見てみましょう。
<script> export let name; </script> <style> h1 { color: purple; } </style> <h1>{name}</h1>
上記のコードには、正確に3つのセクションが含まれています。
script
タグ。コンポーネント内で使用する必要のある変数と関数の宣言を含むオプションのJavaScriptブロックです。別のオプションのブロックである
style
タグ。 重要な違いが1つあることを除けば、一般的なHTMLスタイルタグによく似ています。 このブロック内で説明されているルールは、このコンポーネントのみを対象としています。p
要素にスタイルを適用しても、ページ上のすべての段落に影響するわけではありません。 クラス名を思い付く必要がなく、誤って別のルールを上書きすることがないので、これは素晴らしいことです。最後で唯一必要なブロックはテンプレートブロックです。この場合は
h1
タグです。 これは、コンポーネントのプレゼンテーション/ビューです。 ビューがどのようにスタイル設定され、どのように動作するかを決定するため、スタイルブロックとスクリプトブロックに緊密にバインドされています。
Svelteは、モジュール性をフロントエンドゲームに取り入れようとしているライブラリです。 さまざまなコンポーネントを分離するだけでなく、ロジック、ビュー、およびテンプレートを分離する際にも、そのモジュール性を維持します。
作成しているログインフォームに戻り、 src
フォルダー内に次の内容の新しいファイルLoginForm.svelte
を作成しましょう。
<style> form { background: #fff; padding: 50px; width: 250px; height: 400px; display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: 0px 20px 14px 8px rgba(0, 0, 0, 0.58); } label { margin: 10px 0; align-self: flex-start; font-weight: 500; } input { border: none; border-bottom: 1px solid #ccc; margin-bottom: 20px; transition: all 300ms ease-in-out; width: 100%; } input:focus { outline: 0; border-bottom: 1px solid #666; } button { margin-top: 20px; background: black; color: white; padding: 10px 0; width: 200px; border-radius: 25px; text-transform: uppercase; font-weight: bold; cursor: pointer; transition: all 300ms ease-in-out; } button:hover { transform: translateY(-2.5px); box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.58); } h1 { margin: 10px 20px 30px 20px; font-size: 40px; } </style> <form> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" /> <label>Password</label> <input name="password" type="password" placeholder="password" /> <button type="submit">Log in </button> </form>
これは、後でスマートにするダムスタイルのコンポーネントです。 このコンポーネントをサイトで表示するには、ルートコンポーネントであるApp内にレンダリングする必要があります。 src/App.svelte
を編集して、次のようになります。
<script> import LoginForm from "./LoginForm.svelte"; </script> <style> section { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; background: linear-gradient(to right, #cd76e2, #e358ab); } </style> <section> <LoginForm /> </section>
すべてが正しく行われ、アプリケーションがまだ実行されている場合、フォームはlocalhost:5000
に表示されます。 フォームをよりスマートにすることで、Svelteスキルをレベルアップしましょう。
ステートフルになる
Svelteのどのコンポーネントもその状態を持つことができます。 状態は、テンプレート内で使用できる特殊変数または特殊変数のグループです。 なぜ「特別」と言うのですか? このような変数が変更されるたびに、テンプレートに通知され、コンテンツが最新の状態でレンダリングされます。 これにより、アプリケーションはユーザーの操作に非常に速く反応できます。
適切なフィールドのフォーム値が格納されるemail
とpassword
の状態変数を宣言します。 これは、 email
とpassword
の変数が常にフォームの値と同期することを意味します。したがって、送信値とフォームの実際の値に違いが生じることを恐れずに、いつでもこれらの値を送信する準備ができています。
<script> let email = ""; let password = ""; let isLoading = false; const handleSubmit = () => { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); }; </script> <style> /* Style is unchanged */ </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> {#if isLoading}Logging in...{:else}Log in {/if} </form>
状態変数は一般的なJavaScript変数のように見えますが、フォーム値と同期させる(フォームフィールドにバインドする)には、 bind:value
ディレクティブを使用する必要があります。 なじみのないものもいくつかあります。
on:submit|preventDefault
は、デフォルトイベントの動作を防ぐための省略形です。 毎回e.preventDefault()
を作成するよりも、この方法の方が快適です。{#if isLoading}Logging in...{:else}Log in {/if}
はSvelteのテンプレート構文の一部です。 テンプレートブロックにはJSがないため、if、loopsなどを使用するための特別な構文があります。
最後に、状態を使用してフォームに検証を追加することにより、使用可能なオプションを使用しましょう。 これは、別の状態変数errors
を作成することで実現できます。このエラーは、フォームが無効な値で送信されたときにエラーで埋められます。
<script> let email = ""; let password = ""; let isLoading = false; let errors = {}; const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); } }; </script> <style> // Previous styles unchanged .errors { list-style-type: none; padding: 10px; margin: 0; border: 2px solid #be6283; color: #be6283; background: rgba(190, 98, 131, 0.3); } </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} </form>

フォームはほぼ完成しています。 残っているのは、認証が成功したときの成功メッセージだけです。

成功した送信を追跡するための状態変数を作成しましょう。これはデフォルトではfalse
です。 フォームの送信が成功したら、この変数の値をtrue
に設定する必要があります。
let isSuccess = false;
フォーム送信を処理する関数も、操作が成功した後にisSuccess
を切り替えるロジックに従うように変更する必要があります。
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; isSuccess = true; // Authorize the user }, 1000); } };
この変更により、送信が完了するとすぐにフォームが成功状態になります。
ただし、開発サーバーを確認すると、フォームの動作に変更はありません。 コードを変更しましたが、まだテンプレートに触れていません。 ユーザーが正常にログインしたときに成功メッセージを表示するには、テンプレートに指示を追加する必要があります。Svelteのテンプレート構文を使用すると、これを簡単に実装できます。
<form on:submit|preventDefault={handleSubmit}> {#if isSuccess} <div class="success"> <br /> You've been successfully logged in. </div> {:else} <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} {/if} </form>
プロパティ付きの要約
内部コンポーネントの状態に関するすべてを整理しました。 次に、プロパティまたは「プロップ」と呼ばれる外部依存関係を確認します。 小道具は、コンポーネントに渡される入力または引数であり、コンポーネントに何を表示するか、またはコンポーネントがどのように動作するかを記述します。
プロパティの宣言は、キーワードexport
を除いて、状態に似ています。
<script> export let answer; </script> <p>The answer is {answer}</p>
<script> import Nested from './Nested.svelte'; </script> <Nested answer={42}/>
それはすべてプロパティについてです。 宣言して合格-小道具を使用するために知っておく必要があるすべて。
しかし、これらのプロパティはログインフォームコンポーネントにどのように適用されますか? プロップは、送信関数をプロパティに抽出することで、ログインフォームをより一般的にすることができます。 これにより、このコンポーネントを必要な送信アクション(テストサーバーへのリクエスト、実際のサーバーへのリクエストなど)で使用できるようになります。 この小道具はsubmit
と呼ばれ、送信アクションが成功した場合は解決されたpromiseを返し、エラーが発生した場合は拒否されたpromiseを返す関数になります。 上記の例で小道具を宣言しましょう:
export let submit;
ログインフォーム内の送信ハンドラーも、新しいsubmit
プロパティを使用するように編集する必要があります。
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; submit({ email, password }) .then(() => { isSuccess = true; isLoading = false; }) .catch(err => { errors.server = err; isLoading = false; }); } };
コンポーネントの準備ができているようです。 ただし、フォームに戻って送信しようとすると、ボタンの状態が読み込みから変更されていないことがわかります。 また、コンソールには例外がありますUncaught TypeError: submit is not a function
。 もちろん、私たちは小道具を宣言しましたが、それを渡すのを忘れました。 アプリコンポーネントで関数を宣言し、ログインフォームに渡します。
const submit = ({ email, password }) => new Promise((resolve, reject) => setTimeout(resolve, 1000));
<section> <LoginForm submit={submit} /> </section>
これで、フォームは意図したとおりに機能しています。 エラーを表示し、ログインが成功したかどうかをユーザーに通知することができます。

コンテキスト共有
アプリケーションを構築するために必要なすべてがリストされているようです。 プロパティと内部状態があれば、準備は完了です。 しかし、それは部分的にしか真実ではありません。 これらの2つの一般的なポイントにより、複雑度の高いSPAを設計できます。 ただし、多くの異なるコンポーネント間でデータを共有しようとすると、非常に困難になります。
最も簡単な例は、グローバルにアクセス可能なuser
変数を使用することです。 多くのコンポーネントは、ユーザーの役割、年齢、ステータスなどに応じて、ユーザーに関連する動作を変更する必要があります。ただし、小道具を使用してアプリの各コンポーネントにユーザーを渡すことで、ユーザーを繰り返すことはできません。
Svelteには、これに対するソリューションがあります。コンテキストAPIです。
コンテキストAPIは、データを渡したり、小道具として機能したり、多くのイベントをディスパッチしたりすることなく、コンポーネントが相互に「通信」するためのメカニズムを提供します。 これは高度な機能ですが、便利な機能です。
設計しているログインフォームにユーザーコンテキストを追加しましょう。 次の内容のファイルuserContext.js
をsrc
フォルダー内に作成します。
export const key = "userContext"; export const initialValue = null;
key
はコンテキストの一意の識別子です。アプリケーションには、アクセス可能な状態を維持する必要のあるさまざまなコンテキストが無制限に存在する可能性があるためです。 initialValue
は、設定される前のコンテキストの単なるデフォルト値です。
次のステップは、アプリケーションにコンテキストを追加することです。 App.svelte
ファイルに移動し、2つのインポートステートメントを追加します。
import { onMount, setContext } from "svelte"; import { key as userContextKey, initialValue as userContextInitialValue } from "./userContext";
上記のコードを見ると、 svelte
パッケージから何をインポートしているのか不思議に思うかもしれません。 onMount
は、引数としてコールバック関数を必要とするヘルパー関数です。 このコールバックは、現在のコンポーネントがマウントされているとき(コンポーネントのロードの開始時)に実行されます。 setContext
は、コンテキストのセッター関数です。 コンテキストへのキーとその引数としての新しい値が必要です。
onMount
関数を使用して、コンテキストのデフォルト値を設定しましょう。
onMount(() => { setContext(userContextKey, userContextInitialValue); });
そして、 submit
機能を変更して、ユーザーコンテキストを設定します。
const submit = ({ email, password }) => new Promise((resolve, reject) => { setTimeout(() => { setContext(userContextKey, { name: "Foo", lastName: "Bar", email: "[email protected]" }); resolve(); }, 1000); });
それでおしまい。 送信が成功すると、ユーザーコンテキストが、コンテキストゲッターgetContext
によってアクセスできる偽のユーザーオブジェクトに変更されます。
<script> import { getContext } from 'svelte'; import { key as userContextKey } from "./userContext"; const user = getContext(key); </script>
概要
Svelteは、高性能で柔軟なAPIを備えた強力なツールです。 この投稿で取り上げた基本事項に加えて、Svelteにはすぐに使用できる次の機能があります。
- リアクティブな宣言とステートメント
- テンプレートブロックを待つ
- ディメンションバインディング
- Reduxのようなグローバルストア
- アニメーションとトランジションヘルパー
- デバッグヘルパー
要約すると、Svelteは、SPAの構築などのすべてのニーズを満たす優れたライブラリです。 それは市場で最大のプレーヤーと競争することができ、勝つことさえできます。 ただし、現時点で使用できるのは、フロントエンド開発者コミュニティでのサポートです。
注:この記事のすべてのコードは、 teimurjan/svelte-login-form
リポジトリにあります。 ログインフォームのデモはこちらから入手できます。