jQueryカスタムイベントの管理
-
28-09-2019 - |
質問
私は数時間にわたって追加の研究をしましたが、私はまだ一般的な問題だと思うものに良いパターンを見つけることができません。
.NET MVC2アプリに取り組んでいます。私たちのアプリはメインページで構成されています。その後、多くの部分的なビュー(含まれるページを含む)は、それぞれの部分ビューの1つがウィジェットに対応しています。 HTML 構造と js-jquery 根性
私たちのウィジェットのいくつかは互いに豊富な相互作用を持っているので、もちろん、私たちはJqueryのイベントを使用して、これの効果に何かをバインドしています。
データサマリーウィジェット
$(document).bind("DataUpdated", summaryobject.updateTotals());
データ操作ウィジェット
$(document).trigger("DataUpdated");
私たちが抱えている問題は、ユーザーがアプリケーションの一部に移動すると、これらのウィジェット(HTML/DOM)がページから削除され、新しい部分ビューの新しいセットに置き換えることです。ユーザーがナビゲートすると、HTML(視覚表現)がリロードされ、二重結合が生成されるjQueryバインディングが作成されます。
これまでのところ、私の解決策は私には不自由なようです。
(1)DOMオブジェクトにバインドするバインディングは次のとおりです。
$("#summaryobject").bind("DataUpdated", summaryobject.updateTotals());
これに関する問題は、私のトリガーウィジェットがどのdomがトリガーするかを知る必要があることです。 $("#summaryobject")
その種の目的を打ち負かす。
(2)どのイベントをバインドし、イベントを1回だけバインドできるようにすることを許可するトラクトにEventBusオブジェクトを作成します。私が抱えている問題は、イベントを保存/バインドするとき、誰がそれを作成したかを追跡できないので、必要に応じて登録解除できません。
カスタムイベントを管理するために他の人が使用しているパターンは何ですか?
解決 4
私は今のところこれをすることになりました:
私のページマネージャーオブジェクトの下で、私はこの方法を書きました
function PageManager() {
this.eventBusRegistry = [];
///<summary>Registers Event if not already bound</summary>
this.registerForEvent = function (eventName, eventOwner, functionToBind) {
if (this.eventBusRegistry[eventName + eventOwner] == null) {
this.eventBusRegistry[eventName + eventOwner] = "BOUND";
$(document).bind(eventName, functionToBind);
}
}
}
私のウィジェットのクラスで私はこれをしました。
///<summary>Widget</summary>
function Widget(inWidgetName) {
//the data you wish to update.
this.data = {};
//name of widget
this.widgetName = inWidgetName;
}
Widget.prototype.registerForEvent = function (eventName, functiontoBind) {
//Session is the instance of PageManager
Session.registerForEvent(eventName, this.widgetName, functiontoBind);
};
ウィジェットの任意のインスタンスについては、イベントをバインドするためにRegisterVerventと呼びます。
これは完璧なソリューションとはほど遠いものです。私たちのデザインには、JSオブジェクトを登録しないという点で、メモリリークがまだあります。ただし、オブジェクトはロードされるたびに上書きされます。そのため、より悪いケースは、アプリケーション内のすべてのオブジェクトを使用していなくても、一度登録できることです。
ただし、イベントにメソッドをバインドすると、上書きまたはコースがないドキュメントオブジェクトに結合します。したがって、このコードは私たちが再建を止めます。まだ少しずさんなセットアップがありますが、それは最小限に抑える必要があります。
他のヒント
あなたの問題には2つの良い解決策があります(私が見ることができます)。
すべてを削除します
bind
電話をかけて、1回の呼び出しに置き換えますdelegate
またlive
耳を傾けるリスナーを設定します すべて アプリケーションで発生し、適切な場所にルーティングするイベントの。 (つまり、コントローラーを作成します)。イベントを登録解除および購読することを可能にするEventBusを使用します。 Eventbusでこれを行うために私が見た中で最も簡単な方法はPeter Michaux'sです イベントスクリプト.
/*
Extremely loosely coupled custom events
Source:
http://peter.michaux.ca/articles/anonymous-events-extremely-loose-coupling
*/
EventManager = {};
EventManager.events = {};
EventManager.subscribe = function( event_name, subscriber, method_name ) {
var event = this.events[event_name];
if ( ! event ) {
event = this.events[event_name] = [];
}
event.push( { s: subscriber, m: method_name } );
return this;
};
EventManager.unsubscribe = function( event_name, subscriber ) {
var event = this.events[event_name];
if ( ! event ) {
return;
}
for ( var i = event.length - 1; i >= 0; i-- ) {
if ( event[i].s === subscriber ) {
event.splice( i, 1 );
}
}
return this;
};
EventManager.unsubscribe_all = function( event_name ) {
delete this.events[event_name];
return this;
};
EventManager.fire = function( event_name ) {
var event = this.events[event_name];
if ( ! event ) {
return this;
}
for ( var i = event.length - 1; i >= 0; i-- ) {
subscription = event[i];
subscription.s[subscription.m].apply( subscription.s, arguments );
}
return this;
};
この2番目の方法を使用する例は次のとおりです。
EventManager.subscribe("DataUpdated", summaryobject, "updateTotals");
// ... at some point later on ...
EventManager.fire("DataUpdated");
// Fires `updateTotals` with `this` bound to `summaryobject`
次のように、いくつかのことを試すことができます。
イベントタイプの名前を付けます。このようにして、2つの特定のビューインスタンス間にバインディングを作成していませんが、タイプのビュー間で一般化された関係を作成できます。上記の例から:
データサマリーウィジェットa
$(document).bind("DataUpdated.Statistics", summaryobject.updateTotals());
データ操作ウィジェットa
$(document).trigger("DataUpdated.Statistics");
こちらのドキュメントをご覧ください:http://api.jquery.com/bind/
新しいDOM /ハンドラーをロードする前に、ウィジェットまたはそれらのグループがアンロードされるたびにイベントハンドラーをアンロードする。
使用してみましたか live()
バインディング方法?