Backbone.js 什么时候使用木偶,用木偶绑还是用木偶绑?
这一次,我正在努力使用不同的方法来绑定事件。我已经在代码中列出了所有提到的方法。我只是不知道我是否走对了路。也许我应该始终使用bindTo来确保我的视图在更改后完全关闭(目前这通常会产生错误)?是否有任何最佳实践可以帮助我走上正确的方向 为了说明我目前对木偶的理解,这里是我应用程序中的一个模块。一如往常,每一个暗示都是非常受欢迎的Backbone.js 什么时候使用木偶,用木偶绑还是用木偶绑?,backbone.js,marionette,Backbone.js,Marionette,这一次,我正在努力使用不同的方法来绑定事件。我已经在代码中列出了所有提到的方法。我只是不知道我是否走对了路。也许我应该始终使用bindTo来确保我的视图在更改后完全关闭(目前这通常会产生错误)?是否有任何最佳实践可以帮助我走上正确的方向 为了说明我目前对木偶的理解,这里是我应用程序中的一个模块。一如往常,每一个暗示都是非常受欢迎的 PP.module('Grid', function(Grid, PP, Backbone, Marionette, $, _){ Grid.Product =
PP.module('Grid', function(Grid, PP, Backbone, Marionette, $, _){
Grid.Product = Backbone.Model.extend({});
Grid.ProductCollection = Backbone.Collection.extend({
model: Grid.Product,
url: '/products/query'
});
Grid.ProductView = Backbone.Marionette.ItemView.extend({
className: 'grid',
template: 'public/templates/grid-template'
});
// Helper Methods
// -----------------------
var getGenderCode = function(genderName){
var genderMap = {
'men': 'M',
'women': 'W',
'unisex': 'A'
}
return genderMap.genderName;
}
// Public API
// -------------------
Grid.renderGrid = function(productCollection){
Grid.productView = new Grid.ProductView({
collection: productCollection
});
Grid.productView.bind('show', function(){
$('#isotope-container').isotope({
itemSelector : '.item',
containerStyle: {
position: 'relative',
zIndex: 1
}
});
});
PP.Layout.mainRegion.show(Grid.productView);
}
// Event Handlers
// -----------------------
PP.vent.bind('grid:requested', function(categoryData){
// use bootstrapped data on first start
if (PP.App.bootstrappedCategoryName !== categoryData.categoryName) {
Grid.productCollection.fetch({
data: {
gender: getGenderCode(categoryData.categoryName),
category: categoryData.categoryId
}
});
}
else {
PP.vent.trigger('mainview:ready', {
categoryName: PP.App.bootstrappedCategoryName
});
}
});
// Initializer
// --------------------
PP.addInitializer(function(options){
Grid.productCollection = new Grid.ProductCollection();
Grid.productCollection.on('reset', function(){
Grid.renderGrid(Grid.productCollection);
});
Grid.productCollection.reset(options.newArrivalsList);
});
});
一般的指导原则是,在应用程序的整个生命周期中,当您有一个创建和销毁的对象,并且该对象需要绑定到其他对象的事件时,您应该使用
EventBinder
视图和内存泄漏
视图就是最好的例子。视图总是被创建和销毁。它们还绑定到视图上的模型
和集合
中的许多不同事件。当视图被销毁时,需要清除这些事件。通过在视图上使用内置的bindTo
方法,事件处理程序将为您清理。如果不使用bindTo
而直接使用on
,则必须手动调用off
,以在视图关闭/销毁时解除事件绑定。如果你不这样做,你最终会变成僵尸(内存泄漏)
如果您尚未阅读,请查看以下文章:
自定义事件分组
然而,视图并不是唯一适用的地方,也不是EventBinder
的唯一用例
如果您正在处理少数对象,绑定到它们的事件,并且这些对象可以替换为其他对象实例,那么EventBinder
将非常有用。在这种情况下,可以将EventBinder视为相关对象的事件集合或事件组
假设您有ObjA、ObjB和ObjC。其中每一个都会触发一些事件,并且您希望确保在代码完成时清理事件处理程序。使用EventBinder
,这很容易:
doStuff = {
start: function(a, b, c){
this.events = new Marionette.EventBinder();
this.events.bindTo(a, "foo", this.doSomething, this);
this.events.bindTo(b, "bar", this.anotherThing, this);
this.events.bindTo(c, "baz", this.whatever, this);
},
doSomething: function(){ /* ... */ },
anotherThing: function(){ /* ... */ },
whatever: function(){ /* ... */ },
stop: function(){
this.events.unbindAll();
}
}
doStuff.start(ObjA, ObjB, ObjC);
// ... some time later in the code, stop it
doStuff.stop();
在此代码中调用stop
,将正确清理此用途的所有事件处理程序
何时直接使用打开
/关闭
与此相反的是,您并不总是需要使用EventBinder
。你可以不用它,永远。但你需要记住在必要时清理你的事件
在不需要清理事件处理程序的情况下,也不需要使用EventBinder
。这可能是路由器触发的事件,也可能是木偶应用程序
对象触发的事件。对于那些应用程序生命周期事件,或者需要贯穿整个应用程序生命周期的事件,不要使用EventBinder
。相反,让事件处理程序继续运行。当用户刷新浏览器窗口或导航到其他站点时,处理程序将在该点被清理
但是当您需要管理内存和事件处理程序、清理引用并关闭内容而不刷新页面或离开页面时,然后,
EventBinder
变得很重要,因为它简化了事件管理。我在你的博客文章中读到了类似的内容,但对我来说,你具体而详细的回答更能说明这一点。谢谢!谢谢Derek,非常有用的解释。您提到了开/关,但没有明确提到“bind()”。bind只是开/关的另一种说法吗?他的例子显示了bind,所以我有点困惑,为什么你的详细回复没有提到它。(编辑:我会的,它们是一样的:)看起来bindTo不再适用于1.4版本,而是适用于0.9版本。最好使用bind。