動的スニペット
アプリケーション開発において、テーブルの個々の行やリストの項目などに対してAJAX操作を実行する必要性がしばしば生じます。例として、記事のリストを表示し、ログインしたユーザーが各記事に対して「いいね/いいねしない」の評価を選択できるようにします。AJAXなしのPresenterと対応するテンプレートのコードは、おおよそ次のようになります(最も重要な部分を示します。コードは評価を記録し、記事のコレクションを取得するためのサービスの存在を前提としています – 具体的な実装はこのチュートリアルの目的には重要ではありません):
テンプレート:
Ajax化
では、この簡単なアプリケーションにAJAXを追加しましょう。記事の評価の変更はリダイレクトが必要なほど重要ではないため、理想的にはバックグラウンドでAJAXで行われるべきです。アドオンのハンドリングスクリプト
を使用し、AJAXリンクにはCSSクラス ajax
を付けるという通常の慣習に従います。
しかし、具体的にはどのようにすればよいでしょうか?Netteは2つの方法を提供します:いわゆる動的スニペットの方法とコンポーネントの方法です。どちらにも長所と短所があるため、それぞれを順番に見ていきます。
動的スニペットの方法
動的スニペットとは、Latteの用語では、スニペット名に変数を使用する {snippet}
タグの特定のユースケースを意味します。このようなスニペットはテンプレートのどこにでも配置できるわけではありません –
静的スニペット、つまり通常の、または {snippetArea}
内で囲まれている必要があります。私たちのテンプレートを次のように変更できます。
各記事は、記事IDを名前に含むスニペットを定義します。これらすべてのスニペットは、articlesContainer
という名前の1つのスニペットでまとめてラップされます。このラッピングスニペットを省略すると、Latteは例外で警告します。
残っているのは、Presenterに再描画を追加することです – 静的なラッパーを再描画するだけで十分です。
同様に、姉妹メソッド handleUnlike()
も変更すれば、AJAXは機能します!
しかし、この解決策には1つの欠点があります。AJAXリクエストがどのように進行するかをさらに調査すると、アプリケーションは表面的には効率的に見える(特定の記事に対して1つのスニペットのみを返す)ものの、実際にはサーバー上で全てのスニペットを描画していることがわかります。目的のスニペットをペイロードに配置し、他のスニペットは破棄しました(したがって、それらもデータベースから不必要に取得しました)。
このプロセスを最適化するには、テンプレートに $articles
コレクションを渡す場所(例えば renderDefault()
メソッド内)に介入する必要があります。シグナルの処理が render<Something>
メソッドの前に行われるという事実を利用します。
これで、シグナルの処理中に、すべての記事を含むコレクションの代わりに、描画してペイロードでブラウザに送信したい1つの記事のみを含む配列がテンプレートに渡されます。したがって、{foreach}
は一度だけ実行され、余分なスニペットは描画されません。
コンポーネントの方法
全く異なる解決方法は、動的スニペットを回避します。トリックは、ロジック全体を特別なコンポーネントに移すことです –
これからは、評価の入力はPresenterではなく、専用の LikeControl
が担当します。クラスは次のようになります(それに加えて、render
、handleUnlike
などのメソッドも含まれます):
コンポーネントのテンプレート:
もちろん、ビューテンプレートが変更され、Presenterにファクトリを追加する必要があります。データベースから取得する記事の数だけコンポーネントを作成するため、その「増殖」には Multiplier クラスを使用します。
ビューテンプレートは必要最小限に縮小されます(そして完全にスニペットなし!):
ほぼ完了です:アプリケーションはこれでAJAXで動作します。ここでもアプリケーションを最適化する必要があります。なぜなら、Nette Databaseを使用しているため、シグナルの処理中にデータベースから1つではなく、すべての記事が不必要にロードされるからです。しかし、利点は、実際に私たちのコンポーネントだけがレンダリングされるため、それらの描画が行われないことです。