はじめに
私はVueの開発者ですが、最近業務でsvelteを書くことも多くなってきています。
その中で、svelteのderived
はどんな場面で使うといいのかについて色々悩んでました。
使ってみるとVueのcomputed
と似たような感触があったため、今回はこの二つを比べてみたいと思います。
反応性の基本概念
まず、それぞれのフレームワークがどうやって反応性を実現しているか見てみましょう。
Svelteは、コンパイル時に反応性を解決するアプローチを取っています。
具体的に言うと、Svelteではビルド時にコードを解析し、どの変数がUIに影響するかを特定します。そして単純な変数への代入(count = count + 1
など)が反応性のトリガーになります。変数が更新されたときに必要なDOM更新を行うコードが自動生成される感じです。
その一方、Vue.jsは実行時に依存関係を追跡するプロキシベースの反応性システムを採用しています。Vue 3ではJavaScriptのProxyオブジェクトを使用して、プロパティへのアクセスと変更を渡します。
レンダリング中にアクセスされたプロパティを記録し、それらの依存関係を作成して、プロパティが変更されるとそのプロパティに依存しているすべての箇所(コンポーネントやcomputed、watchなど)を再評価します。
Svelteのderived
ストア
derived
ストアは、他のストアから値を派生させるために使用されます。
元のストアが更新されると、derived
ストアも自動的に新しい値を計算します。このストアの値が変わったら、それを使って新しい値を計算するよって感じですね。
以下のような書き方です。
import { writable, derived } from 'svelte/store';
// ストアを作成
const count = writable(0);
// ストアからから派生したストアを作成
const doubledCount = derived(count, $count => $count * 2);
derived
は宣言的に値がどのように変換されるかを定義します。
同期的、非同期両方サポートしていて、依存するストアが更新されると自動的に値が更新されます。
また、入力値が変わらなければ再計算されないメモ化(キャッシュ)の特徴もあります。
Vueのcomputed
computed
は、他のリアクティブなもの(refとか)から新しい値を計算するための機能です。
依存する値が変わると自動的に再計算されます。
基本的にはこんな感じで使います。
import { ref, computed } from 'vue';
const count = ref(0);
const name = ref('John');
// 一つのソースから
const doubledCount = computed(() => count.value * 2);
// 複数のソースから
const greeting = computed(() => {
return `Hello, ${name.value}! Count: ${count.value}`;
});
computed
は値がどのように計算されるかを定義します。
依存する値が変更されるまで再評価されず、依存関係が変更されない限り計算結果はキャッシュされます。
主な違い
アプローチの違い
Svelteのderived
はストアから新しいストアを作成するためのもので、Vueのcomputed
は反応性データから派生した値を計算するためのものです。
使用コンテキストの違い
derived
はSvelteのストアの一部で、通常はコンポーネント外で定義されます。
一方、computed
はVueのコンポーネントのライフサイクルに密接に関連しており、通常はコンポーネント内で定義されます。
おわりに
普段使っているフレームワークの内部までちゃんと理解すると、バグなどに遭遇した時にも対応しやすくなる気がしますね!