最近の投稿「Svelte 5 への移行の経験と注意点」に続き、Svelte 4 から Svelte 5 に移行する際のいくつかのテクニックと考え方の変化を強調したいと思います。
Svelte 4 は「魔法の」 $: を使用し、コードをリアクティブにするための面倒な作業をすべて実行させます。
のような変数の再代入も採用しました。
<script> let arr = [1, 2, 3] let value = 4 arr = [...arr, value] </script>
プッシュなどの変数を更新/変更するメソッドの代わりに
Svelte 5 を使用して古き良き JS パターンを学び直すことに非常に驚きました。
そして、私はおそらく Svelte 4 の let にかなり甘やかされました。反応性についての理由はなく、必要に応じて組み込まれました。 ただし、すべての変数がリアクティブである必要はありません。また、非リアクティブ変数は、リアクティブまたは「従来の変更コード」で更新される場合もあります。リアクティブ変数が実際に必要になるのは、それを UI で使用するときです (この変数が html/page でレンダリングされ、後で更新する必要があるとき)。
Svelte 5 では、派生状態に割り当てられない、独自のスコープで参照されている状態が更新されないなどのエラーが発生する可能性があります。クロージャ内で参照するつもりでしたか?または、derived_references_selfn Svelte 4 コーディング スタイルを使用している場合、派生値自体を再帰的に参照することはできません。
Svelte 4 スタイルのコードの例を見てください:
<script> let value; let derivedArr = [] $: if (value) { derivedArr = [...derivedArr, value] } function random () { value = Math.floor(1 + Math.random() * 10) } </script> <button on:click="{random}">Generate Random Value</button> <p>value: {value}</p> <p>derivedArr: {derivedArr}</p>
デモ
2 つのリアクティブ変数があり、Svelte 4 は更新を自動的に解決します。正しい方法は変数を再割り当てすることであることを覚えておくだけで済みました。
Svelte 5 では、同じ結果を達成する方法を少し考える必要があります。使用している 2 つの変数では不十分です。もう 1 つ、ヘルパー変数が必要です。
推奨される方法は、$derived() ルーンを使用することです。
<script> let value = $state(); let helperArr = []; let derivedArr = $derived.by(() => { if (value) { helperArr.push(value); return helperArr; } }); function random () { value = Math.floor(1 + Math.random() * 10) } </script> <button onclick="{random}">Generate Random Value</button> <p>value: {value}</p> <p>derivedArr: {derivedArr}</p>
デモ
これを行うより簡単な方法を知っている場合は、私に知らせてください。
同じことを実現する $effect() ルーン方法もあります。さらに単純に見えるかもしれませんが、可能であればエフェクトは避けるべきです (主に Svetlet 5 エフェクトはサーバー/SSR 上で実行されません)。
<script> let value = $state(); let helperArr = [] let effectArr = $derived(helperArr); $effect.pre(() => { if (value) { helperArr.push(value) } }) function random () { value = Math.floor(1 + Math.random() * 10) } </script> <button onclick="{random}">Generate Random Value</button> <p>value: {value}</p> <p>effectArr: {effectArr}</p>
デモ
これは、Svelte 4 のページを Svelte 5 に非常に簡単に移行しようとした例です。コードを再考するのに時間がかかりました。このページは、「もっと読み込む」機能を備えた投稿検索として機能します (ユーザーが JS を持っていない場合は結果を追加するかページングします):
スヴェルト 4
'../components/Icon.svelte' からアイコンをインポートします。 import { 拡張 } から '$app/forms'; 'svelte' から { ティック } をインポートします。 let フォームをエクスポートします。 エクスポート let searchLang; エクスポート let l; 結果を = []; にします。 前検索 = ''; searchTerm をみましょう。 スキップしましょう。 $: if (!!フォーム && フォーム?.thereIsMore) { searchTerm = フォーム.searchTerm; スキップ = 数値(フォーム?.スキップ) 20; } $: if (!!form?.searchResultFromAction) { if (previousSearch == form.searchTerm && form.thereWasMore) { 結果 = [...結果, ...form.searchResultFromAction]; } それ以外 { 結果 = [...form.searchResultFromAction]; 前の検索 = form.searchTerm; } } 非同期関数 intoView(el) { ティックを待ちます(); if (el.attributes.index.nodeValue == スキップ - 20 && スキップ != 未定義) { el.scrollIntoView({ 動作: 'スムーズ' }); } } スクリプト> {#if results.length} <ol> {#それぞれの結果をアイテム、インデックスとして表示} <li use:intoview aria-posinset="{index}"> <!-- JavaScript を使用していないユーザーは、ページ分割内で結果の順序を計算しており、CSS により標準の UL 番号付けが無効になっています --> <!-- JavaScript を使用するユーザーには、標準的な UL 番号付けと追加機能の読み込み機能があります --> <noscript>{数値(インデックス) 1 数値(フォーム?.スキップ)}。 </noscript> <a href="/act/%7BsearchingLang%7D/%7Bitem.id%7D/present/text">{item.title}</a> </li> {/それぞれ} </ol> {#if フォーム?.thereIsMore} <!-- これは非表示の入力であるため、おそらく値をバインドする必要はありません --> <!-- <input name="searchTerm" type="hidden" binding:value={searchTerm} /> --> <input name="searchTerm" type="hidden" value="{searchTerm}">; ラベル> <button aria-label="さらに検索結果を読み込むボタン"> <p>スヴェルト 5<br> </p> <pre class="brush:php;toolbar:false"> '../components/Icon.svelte' からアイコンをインポートします。 import { 拡張 } から '$app/forms'; 'svelte' から { ティック } をインポートします。 let { フォーム、searchLang、l } = $props(); 前検索 = ''; let Skip = $derived.by(() => { if (!!フォーム && フォーム?.thereIsMore) { 戻り値 Number(form?.skip) 20; } }); helperResultsArr = []; let results = $derived.by(() => { if (!!form?.searchResultFromAction) { if (previousSearch == form.searchTerm && form.thereWasMore) { helperResultsArr.push(...form.searchResultFromAction); helperResultsArr を返します。 } それ以外 { helperResultsArr = []; helperResultsArr.push(...form.searchResultFromAction); 前の検索 = form.searchTerm; helperResultsArr を返します。 } それ以外の場合は [] を返します。 }); 非同期関数 intoView(el) { ティックを待ちます(); if (el.attributes.index.nodeValue == スキップ - 20 && スキップ != 未定義) { el.scrollIntoView({ 動作: 'スムーズ' }); } } スクリプト> {#if results.length} <ol> {#それぞれの結果をアイテム、インデックスとして表示} <li use:intoview aria-posinset="{index}"> <!-- JavaScript を使用していないユーザーは、ページ分割内で結果の順序を計算しており、CSS により標準の UL 番号付けが無効になっています --> <!-- JavaScript を使用するユーザーには、標準的な UL 番号付けと追加機能の読み込み機能があります --> <noscript>{数値(インデックス) 1 数値(フォーム?.スキップ)}。 </noscript> <a href="/act/%7BsearchingLang%7D/%7Bitem.id%7D/present/text">{item.title}</a> </li> {/それぞれ} </ol> {#if フォーム?.thereIsMore} <input name="searchTerm" type="hidden" value="{form.searchTerm}"> ラベル> <button aria-label="さらに検索結果を読み込むボタン"> <p>今回はここまでです。 </p> <p>追記: 別の方法で移行を行う場合は、遠慮なくお知らせください。</p> </button>
以上がSvelte 5 の「ヘルパー」変数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。