JavaScript では、エージェントとデリゲート がよく登場します。
それでは、どのような状況で使用されるのでしょうか?その原理は何ですか?
ここでは、JavaScript デリゲートの使用法と原理、および Dojo、jQuery、およびその他のフレームワークのデリゲート インターフェイスを紹介します。
JavaScript イベントプロキシ
イベント プロキシは、JS の世界では非常に便利で興味深い機能です。多くの要素にイベントを追加する必要がある場合は、イベントを親ノードに追加し、そのイベントを親ノードに委任することで、ハンドラー関数をトリガーできます。
これは主にブラウザのイベント バブリング メカニズムによるものです。この機能の使用方法を説明するために具体的な例を示します。
この例は主に David Walsh の関連記事 (JavaScript イベント委任の仕組み) から引用したものです。
Li の多くの子ノードを含む UL の親ノードがあるとします。
<ul id="list"> <li id="li-1">Li 1</li> <li id="li-2">Li 2</li> <li id="li-3">Li 3</li> <li id="li-4">Li 4</li> <li id="li-5">Li 5</li> </ul>
マウスが Li 上に移動すると、この Li の関連情報を取得し、フローティング ウィンドウをポップアップして詳細情報を表示する必要があります。または、Li がクリックされたときに、対応する処理イベントをトリガーする必要があります。
通常の記述方法は、onMouseOver や onClick などのイベント リスナーを各 Li に追加することです。
function addListenersLi(liElement) { liElement.onclick = function clickHandler() { //TODO }; liElement.onmouseover = function mouseOverHandler() { //TODO } } window.onload = function() { var ulElement = document.getElementById("list"); var liElements = ulElement.getElementByTagName("Li"); for (var i = liElements.length - 1; i >= 0; i--) { addListenersLi(liElements[i]); } }
この UL の Li サブ要素が頻繁に追加または削除される場合、Li が追加されるたびに addListenersLi メソッドを呼び出して、各 Li ノードのイベント ハンドラーを追加する必要があります。
これにより、追加または削除のプロセスが複雑になり、エラーが発生する可能性があります。
この問題の解決策は、イベントが上位の親ノードにスローされるときに、イベントのターゲット オブジェクト (ターゲット) を確認することでイベント ソース Li を決定し、取得することです。
次のコードは目的の効果を実現できます:
/ 获取父节点,并为它添加一个click事件 document.getElementById("list").addEventListener("click",function(e) { // 检查事件源e.targe是否为Li if(e.target && e.target.nodeName.toUpperCase == "LI") { // //TODO console.log("List item ",e.target.id," was clicked!"); } });
親ノードにクリック イベントを追加します。子ノードがクリックされると、子ノードからクリック イベントが発生します。親ノードはイベントをキャプチャした後、e.target.nodeName を判断して、それが処理する必要があるノードであるかどうかを判断します。そして、クリックされた Li ノードを e.target を通じて取得します。このようにして、対応する情報を取得して処理することができます。
イベントのバブリングとキャプチャ
ブラウザ イベントのバブリング メカニズム: ブラウザの製造元によって、イベントのキャプチャと処理に異なる処理メカニズムが用意されています。ここでは、W3C によって DOM2.0 用に定義された標準イベントを紹介します。
DOM2.0 モデルは、イベント処理プロセスを 3 つの段階に分割します。
1. イベントキャプチャフェーズ、
2.イベント対象ステージ、
3. イベントバブリングステージ。
以下に示すように:
イベント キャプチャ: 要素がイベント (onclick など) をトリガーすると、トップレベルのオブジェクト ドキュメントがイベント ストリームを発行し、DOM ツリーのノードとともにターゲット要素ノードに到達するまで流れます。イベントが実際に発生するターゲット要素。このプロセス中、イベントの対応するリスニング機能はトリガーされません。
イベント対象: 対象要素に到達後、対象要素のイベントの対応する処理関数を実行します。リスニング関数がバインドされていない場合、その関数は実行されません。
イベントバブリング: ターゲット要素から開始して最上位要素に伝播します。途中で対応するイベント処理関数にバインドされたノードがある場合、これらの関数は一度にトリガーされます。イベントのバブリングを防ぎたい場合は、e.stopPropagation() (Firefox) または e.cancelBubble=true (IE) を使用してイベントのバブリングを防ぐことができます。
jQuery と Dojo のデリゲート関数
Dojo と jQuery で提供されるイベント プロキシ インターフェイスの使用方法を見てみましょう。
jQuery:
$("#list").delegate("li", "click", function(){ // "$(this)" is the node that was clicked console.log("you clicked a link!",$(this)); });
jQuery のデリゲート メソッドには、セレクター、時間名、イベント ハンドラーの 3 つのパラメーターが必要です。
Dojo は jQuery に似ていますが、唯一の違いはプログラミング スタイルです。
require(["dojo/query","dojox/NodeList/delegate"], function(query,delegate){ query("#list").delegate("li","onclick",function(event) { // "this.node" is the node that was clicked console.log("you clicked a link!",this); }); })
Dojo のデリゲート モジュールは dojox.NodeList にあり、jQuery と同じインターフェースと同じパラメーターを提供します。
委任を通じて、開発にイベント委任を使用するいくつかの利点を実現できます。
1. 管理機能が少ない。要素ごとにリスナー関数を追加する必要はありません。同じ親ノードの下にある同様の子要素の場合、イベントは親要素の listen 関数に委任することで処理できます。
2. 要素を動的に簡単に追加および変更でき、要素の変更によってイベント バインディングを変更する必要がありません。
3. JavaScript ノードと DOM ノード間の接続が少なくなり、循環参照によって引き起こされるメモリ リークの可能性が減少します。
JavaScript プログラミングでのプロキシの使用
上記の導入は、DOM イベントを処理するときにブラウザーのバブリング メカニズムを使用して DOM 要素にイベント プロキシを追加することです。実際、純粋な JS プログラミングでは、このプログラミング モデルを使用して、ターゲット オブジェクトを操作するためのプロキシ オブジェクトを作成することもできます。
var delegate = function(client, clientMethod) { return function() { return clientMethod.apply(client, arguments); } } var Apple= function() { var _color = "red"; return { getColor: function() { console.log("Color: " + _color); }, setColor: function(color) { _color = color; } }; }; var a = new Apple(); var b = new Apple(); a.getColor(); a.setColor("green"); a.getColor(); //调用代理 var d = delegate(a, a.setColor); d("blue"); //执行代理 a.getColor(); //b.getColor();
上記の例では、delegate() 関数によって作成されたプロキシ関数 d を呼び出すことによって a の変更が実行されます。
このメソッドは呼び出し元オブジェクトの転送を実現するために apply (call も使用できます) を使用しますが、特定のオブジェクトをプログラミング モードから隠し、これらのオブジェクトが不用意にアクセスされ変更されないように保護できます。
委任の概念は、メソッドの実行スコープを指定するために多くのフレームワークで使用されています。
代表的なものには、dojo.hitch(scope, method) や ExtJS の createDelegate(obj, args) などがあります。
以上がこの記事の全内容です。JavaScript プログラミングを学習する皆さんのお役に立てれば幸いです。