さて、タイトルは少しクリックベイトです。匿名関数を小道具として使用する必要がある場合がありますが、おそらくそれははるかに少ないと思います。まず、問題について説明しましょう。
Svelte や React などのコンポーネント ライブラリでは、コンポーネントの小道具として使用される匿名関数が一種の怠惰な頼りになるものとなり、大規模になると肥大化する恐れがあります。
非常に多くの開発者がこれを行っているのを見てきました:
<button onclick={() => handleSubmit()}>Submit</button>
これの代わりに:
<button onclick={handleSubmit}>Submit</button>
これらの各コード ブロックは文字通りまったく同じ結果を達成します。唯一の違いは、最初の例では匿名関数が挿入されており、引数なしで名前付き関数を呼び出すだけであることです。
アノンアプローチを使用することがなぜ問題になるかわかりますか?このボタンがレンダリングされるたびに、まったく新しい anon 関数が作成され、メモリに保持されます。同じページ上にこれらを 10 個レンダリングすると、10 個の異なる匿名関数がメモリに保持されることになります。
ここで、「わかったけど、たとえば 1 ページに 10 個や 20 個以上のインタラクティブ要素を含める頻度はどのくらいでしょうか?」と思われるかもしれません。その答えは、「これは特殊なケースだと思うかもしれませんが、想像以上に現実に起こります。そして、良い習慣を身につけて、エッジに備えたほうが良いでしょう。」
これが問題となる主な例は、行や項目の削除や編集などの対話型機能を備えた大きなテーブルやリストです。たとえば、ページ上にデータ グリッド タイプのコンポーネントがあり、そのページネーションがページあたり 100 行である場合、各行が作成する匿名関数が 100 回存在することになります。すべての行に何らかの処理を行うチェックボックスと、[編集] ボタンと [削除] ボタンがある場合、名前が付けられ宣言され、匿名関数によって呼び出される元の 3 つの関数に加えて、300 個の匿名関数がメモリに保持されることになります。
プリレンダリングのようなトリックを実行し、効率化のためにデータの次のページを非表示にすると、さらに悪いことになります。この例では、600 個の匿名関数インスタンスがメモリ内に存在することになります。
この習慣がこれほど蔓延し、根付いている理由は少なくとも 2 つ考えられます。
少なくとも Svelte では、関数が確実にリアクティブに呼び出されるようにするためにこれを行う必要がある場合があります。ロジックを予測どおりに動作させるためにこれを行う必要がある状況は他にもあるかもしれません。私が React を使ってから数年になりますが、そのライブラリにも同様の例がいくつかあるはずです。
ただし、これらはコーディング中に必要に応じて対処できるエッジケースです。
これがおそらく最も一般的な原因です。これにより、ある種の状態を関数に直接渡すことができるため、Svelte や React などの UI ライブラリを初めて学習するときに、理解しやすく、操作しやすくなります。おそらくそれが、ほとんどのチュートリアルで匿名関数を小道具として表示する理由です。
これが例です (Svelte 5 の場合):
<button onclick={() => handleSubmit()}>Submit</button>
素敵で清潔ですね?ただし、このページにこのボタンのインスタンスが何百もある場合、潜在的なパフォーマンスの問題が発生します。これをリファクタリングしてパフォーマンスをさらに向上させるにはどうすればよいでしょうか?
プログラミングではよくあることですが、シンプルで簡単な解決策は、EditButton などの個別のコンポーネントを作成し、productId のスコープをそのインスタンスだけに設定することです。したがって、ハンドラー関数には何も渡す必要はありません。ハンドラー関数は、productId が何であるかをすでに知っている個別のコンポーネント内にあるためです。コードがモノリシックではなくモジュール化されている方が一般的に良いのはこのためです。
可能であれば、最初にこの解決策を試してみるべきです。また、コンポーネントは 1 つの productId のみを処理するように分離されているため、その匿名関数は必要ないことに注意してください。代わりに、コンポーネント関数がそれを直接処理できます。
<button onclick={handleSubmit}>Submit</button>
しかし、システム アーキテクチャなどの理由で、更新ロジックをこのようにローカルなスケールに限定できない場合があります。この種の状況に対処するために、はい、もう少し複雑で、言いたくないのですが、anon 関数をプロップとして送信するよりも宣言的ではないことを行います。しかし、それでも非常に読みやすく、大量のアノン関数をメモリにプッシュしないという目的には適しています。
これには、処理しているイベント (クリックなど) を取得する HTML 要素のデータ属性を使用することが含まれます。そしてそれは次のようになります:
// EditButton.svelte <script> // productId is sent to this component as a prop let { productId } = $props() </script> const onEditToggle = (productId) => { // Do some stuff with productId... } <button onclick={() => onEditToggle(productId)}> Edit </button>
そこで何が起こっているかわかりますか? EditButton 内の HTML ボタン要素のカスタム データ属性に製品 ID を入力します。ハンドラー関数が起動すると、要素のデータ属性から製品 ID を直接取得できます。
これで、メモリ内で宣言された関数は 1 つだけ、onEditToggle になり、他のすべては参照によってそれを指すだけです。
私の個人的な感想は、コンポーネントをモノリシックにしてこれらすべてを内部で決定する必要があるのではなく、重要なデータの受け渡しが props を通じてそのコンポーネントに直接行われるように、常に十分にモジュール化されたコードから始めることです。これは、私が上記の「よりシンプルな解決策」で説明していることです。
それがどうしてもできない場合は、データ属性を使用した 2 番目の解決策を選択してください。
anon 関数を使用する方が、データ属性を処理するよりも少し読みやすいため、最初はそれを使用する方が良いため、パフォーマンスの問題が発生した場合に後で調整するだけでよいと主張することもできます。
私はその考え方に一般的に同意しますが、これは、この方法で実行することによる複雑さが少しよくあるケースの 1 つであり、常に同じ方法で実行する必要があります。こうすることで、一方のアプローチともう一方のアプローチを使用するかどうか、いつ使用するかを考える必要がなくなります。どちらも機能し、これらのパフォーマンス上の問題があることがわかった場合でも、後でリファクタリングする必要はありません。
Svelte がトランスパイル中に何らかの方法でこれを処理し、これらの非ノン関数を何らかの形で滑らかにする可能性は十分にあります。私は Svelte のランタイムやコンパイラについて確かなことを言えるほど専門家ではありません。しかし、個人的には、これは、最終的に使用する可能性のあるどの JS ライブラリにも適用されるより安全なパターンであると感じているため、事前に採用する方が良い習慣です。
どう思いますか?対位法はありますか?それとも、Svelte の実行時およびコンパイル レベルで何が起こっているかについての洞察を提供して、私の意見を変える可能性があるでしょうか?コメント欄でお知らせください!
以上がProps での匿名関数の使用をやめてください。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。