2012-01-26 9 views
4

私は、特定の要素が継承する一般的な要素のバックボーンビューを持っています。私は、すべての要素に適用する必要があるイベント処理ロジックと、子タイプの要素に固有のイベント処理ロジックを持っています。子ビューには、親ビューでも処理されるイベントに対する独自のコールバックがあるため、両方でイベントハッシュを使用しようとすると、子コールまたは親コールバックのいずれも呼び出されません。私はいくつかのコードで説明してみましょう:継承したBackbone.jsのイベントハッシュを上書きするビュー

var ElementView = Backbone.View.extend({ 
    events: { 
    "mouseup": "upHandler", 
    "mousedown": "downHandler", 
    "mousemove": "moveHandler" 
    }, 

    initialize: function() { 
    // add events from child 
    if (this.events) 
     this.events = _.defaults(this.events, ElementView.prototype.events); 

    this.delegateEvents(this.events); 
    } 
}); 

var StrokeView = ElementView.extend({ 
    events: { 
    "mousemove": "strokeMoveHandler" 
    } 
}); 

私は、後に相続の別のレベルを持つことになります場合は特にどのように私は、拡張可能な方法でこれを解決するのでしょうか?これを処理する

答えて

8

一つの方法は、イベントのために、「名前空間」を使用することです:

var ElementView = Backbone.View.extend({ 
    events: { 
    "mouseup.element": "upHandler", 
    "mousedown.element": "downHandler", 
    "mousemove.element": "moveHandler" 
    }, 

    initialize: function() { 
    // add events from child 
    if (this.events) 
     this.events = _.defaults(this.events, ElementView.prototype.events); 

    this.delegateEvents(this.events); 
    } 
}); 

var StrokeView = ElementView.extend({ 
    events: { 
    "mousemove.strokeview": "strokeMoveHandler" 
    } 
}); 

は実際には、このアプローチはsuggested in Backbone.js documentationです。

+1

あなたのイベントと名前空間が逆転しているとは思いますが、良い提案です。それは "mouseup:element"ではないでしょうか? –

+0

@RobHruskaこれはドキュメンテーションが示唆しているものではなく、「野生の中の」例も私の推奨する使用法を指しています。最終的には、イベント名をどのように構造化するかはあなた次第です。 –

+1

それは素晴らしいです。私はそれらを頻繁に使用せず、主にjQueryがどのように動作するかについて、主に私が見た他の例から外しています:http://docs.jquery.com/Namespaced_Events。 –

4

私には、JavaScriptのfaux- superBackbone.js documentationで述べたように、初期化機能魔法がinitialize関数内でイベントを設定することで起こる

var ElementView = Backbone.View.extend({ 
    events: { 
    "mouseup": "upHandler", 
    "mousedown": "downHandler", 
    "mousemove": "moveHandler" 
    }, 

    initialize: function() { 
    this.delegateEvents(); 
    } 
}); 

var StrokeView = ElementView.extend({ 
    initialize: function() { 
    this.events = _.extend({}, this.events, { 
     "mousemove": "strokeMoveHandler" 
    }); 

    // Call the parent's initialization function 
    ElementView.prototype.initialize.call(this); 
    } 
}); 

var SubStrokeView = StrokeView.extend({ 
    initialize: function() { 
    this.events = _.extend({}, this.events, { 
     "click": "subStrokeClickHandler", 
     "mouseup": "subStrokeMouseupHandler" 
    }); 

    // Call the parent's initialization function 
    StrokeView.prototype.initialize.call(this); 
    } 
}); 

var c = new SubStrokeView(); 
console.log(c.events); 

// Should be something like 
// click: "subStrokeClickHandler" 
// mousedown: "downHandler" 
// mousemove: "strokeMoveHandler" 
// mouseup: "subStrokeMouseupHandler" 

を活用して、似何かをやりました。プロトタイプに複数のeventsアトリビュートがある場合、JavaScriptはプロトタイプの仕組みのために最も最近設定されたアトリビュートのみを表示します。

は代わりに、この方法でそれをすることによって、各ビューは、その後、独自のthis.eventsを設定し、順番にようにそのイベントとthis.events、およびを拡張親のinitialize関数を呼び出します。

あなたは、この特定の方法でthis.eventsを設定する必要があります:

this.events = _.extend({}, this.events, ...new events...); 

代わりの

_.extend(this.events, ...new events...); 

第二の方法は、イベントが親の(ElementView)プロトタイプ内のオブジェクトのmungeますそれをやって。最初の方法は、各モデルが独自のコピーを取得することを保証します。

+0

私はこの解決策が好きですが、残念ながらmoveHandlerとstrokeMoveHandlerの両方がマウス移動イベントで呼び出されるようにするという問題は扱いません。 – troyastorino

+0

@troyastorino:そのユースケースを処理する適切な方法は、子メソッド内から親メソッドを呼び出すことです。たとえば、次のようになります。 'strokeMoveHandler:function(){ElementView.prototype.moveHandler.call(this); // doDropMoveHandlerもの} '' –

関連する問題