在我的简单项目中,我有2个视图 - 订单项视图(品牌)和应用。我附加了允许选择多个项目的功能:
var BrandView = Backbone.View.extend({ ...some code... toggle_select: function() { this.model.selected = !this.model.selected; if(this.model.selected) $(this.el).addClass('selected'); else $(this.el).removeClass('selected'); return this; } }); var AppView = Backbone.View.extend({ ...some code... delete_selected: function() { _.each(Brands.selected(), function(model){ model.delete_selected(); }); return false; }, });
事情是,我想知道选择了多少项。在此设置中,选择不会影响模型,因此不会触发任何事件。从MVC概念我明白,观点不应直接与其他观点交谈。那么AppView如何知道BrandViews中正在选择某些内容?
更具体地说,我在AppView中知道选择了多少项,所以如果选择了多个项目,我会显示一个菜单供多选。
答案 0 :(得分:73)
您可能希望阅读有关Backbone pub / sub events的讨论:
我喜欢将其作为全局事件机制添加:
Backbone.pubSub = _.extend({}, Backbone.Events);
然后在一个视图中,您可以触发事件:
Backbone.pubSub.trigger('my-event', payload);
另一个你可以听:
Backbone.pubSub.on('my-event', this.onMyEvent, this);
答案 1 :(得分:7)
我使用Addy Osmani所谓的中介模式http://addyosmani.com/largescalejavascript/#mediatorpattern。整篇文章非常值得一读。
基本上它是一个事件管理器,允许您订阅和发布事件。因此,您的AppView将下标到一个事件,即“已选择”。然后BrandView将发布'选定'事件。
我喜欢这个的原因是它允许你在视图之间发送事件,而不会将视图直接绑定在一起。
例如
var mediator = new Mediator(); //LOOK AT THE LINK FOR IMPLEMENTATION
var BrandView = Backbone.View.extend({
toggle_select: function() {
...
mediator.publish('selected', any, data, you, want);
return this;
}
});
var AppView = Backbone.View.extend({
initialize: function() {
mediator.subscribe('selected', this.delete_selected)
},
delete_selected: function(any, data, you, want) {
... do something ...
},
});
这样您的应用视图就不关心它是发布'选定'事件的BrandView或FooView,只是发生了事件。因此,我发现在应用程序的各个部分之间管理事件是一种可维护的方式,而不仅仅是视图。
如果您进一步了解“Facade”,可以创建一个很好的权限结构。这将允许您说只有'AppView'可以订阅我的'选定'事件。我觉得这很有用,因为它非常清楚地说明了事件的使用位置。
答案 2 :(得分:1)
忽略您在帖子中已经提到的问题,您可以绑定和触发事件到/来自全局Backbone.Event对象,这将允许任何事情与其他任何事物进行对话。绝对不是最好的解决方案,如果你有相互聊天的观点,那么你应该考虑重构。但是你去了!希望这会有所帮助。
答案 3 :(得分:1)
这是我的情况,类似的需求:Backbone listenTo似乎是一个解决方案,重定向到登录页面超时或未经过身份验证的请求。
我在路由器中添加了事件处理程序,并使其监听全局事件,例如:
Backbone.Router.extend({
onNotAuthenticated:function(errMsg){
var redirectView = new LoginView();
redirectView.displayMessage(errMsg);
this.loadView(redirectView);
},
initialize:function(){
this.listenTo(Backbone,'auth:not-authenticated',this.onNotAuthenticated);
},
.....
});
并在我的jquery ajax错误处理程序中:
$(document).ajaxError(
function(event, jqxhr, settings, thrownError){
.......
if(httpErrorHeaderValue==="some-value"){
Backbone.trigger("auth:not-authenticated",errMsg);
}
});
答案 4 :(得分:1)
您可以使用Backbone对象作为事件总线。
这种方法稍微清晰但仍然依赖于Global Backbone对象
public SearcherString()
{
Path = new List<Path>();
}
答案 5 :(得分:0)
使用相同的模型对象。可以使用集合初始化AppView,并使用该集合中的一个模型初始化BrandView。当分支对象的属性发生更改时,任何其他引用该模型的代码都可以读取它。
因此,您可以通过集合获取一些品牌:
var brands = new Brands([]);
brands.fetch();
现在您为每个模型制作一个AppView和一系列BrandView。
var appView = new AppView({brands: brands});
var brandViews = brands.map(function(brand) {
return new BrandView({brand: brand});
});
appView和brandViews现在都可以访问相同的模型对象,所以当你更改一个时:
brands.get(0).selected = true;
然后,当它被引用它的视图访问时它也会改变。
console.log(appView.brands.get(0).selected); // true
console.log(brandViews[0].brand.selected) // true
答案 6 :(得分:0)
与John上面提到的相同,Mediator Pattern在这种情况下非常有效,因为Addy Osmani在Backbone fundamentals中再次总结了这个问题。
使用简单而且很棒的Backbone.Mediator插件重击,让我的AMD View模块无缝协同工作=)