2012-01-26 37 views
4

我有一个骨干视图的特定元素将继承的一般元素。我有需要应用于所有元素的事件处理逻辑以及特定于子类型元素的事件处理逻辑。我遇到了麻烦,因为子View对于也由父视图处理的事件有其自己的回调,因此当我尝试在两者中使用事件散列时,子对象或父对象回调从不会被调用。让我说明了一些代码:覆盖事件哈希继承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- super作为Backbone.js documentation所提及的初始化函数

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" 

,奇迹发生了由initialize函数内设置活动项目做了类似的东西。如果您的原型中有多个events属性,则由于原型设计的工作原理,JavaScript只会查看最近一次设置的属性。

相反,通过做这种方式,每个视图设置自己的this.events,然后调用其父initialize功能,又扩展this.events与它的事件,等等。

你需要设置this.events在这种特定的方式:的

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

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

,而不是做它的第二个方式将Munge时间的事件对象的父(ElementView)原型内。第一种方法确保每个模型都有自己的副本。

+0

我喜欢这个解决方案,但不幸的是,它并没有处理我希望moveHandler和strokeMoveHandler在鼠标移动事件上被调用的问题。 – troyastorino

+0

@troyastorino:处理该用例的正确方法是从您的子方法中调用父方法。例如: 'strokeMoveHandler:function(){ElementView.prototype.moveHandler.call(this); //做strokeMoveHandler的东西}' –