我得到以下嵌套视图结构:
LayoutView
- SidebarView
- ContactListView
- ContactItemView
- ContentView
现在想象以下情况:
用户单击 ContactItem。现在,ContactItem 应该调用一个事件或其他东西,以在 ContentView 中呈现单击的联系人的配置文件。
我不知道如何在不破坏灵活性的情况下做到这一点......
我得到以下嵌套视图结构:
LayoutView
- SidebarView
- ContactListView
- ContactItemView
- ContentView
现在想象以下情况:
用户单击 ContactItem。现在,ContactItem 应该调用一个事件或其他东西,以在 ContentView 中呈现单击的联系人的配置文件。
我不知道如何在不破坏灵活性的情况下做到这一点......
一种方法是使用事件聚合器,它使您的视图能够订阅某些事件。这将允许您将视图彼此分离。您的视图不需要相互了解,它们只需要跟踪某些事件。有关如何执行此操作的精彩教程,请参阅Derick Bailey关于该主题的出色帖子。
您可能希望使用事件将它们连接在一起,而不是让 ContactItemView 直接调用 ContentView。在创建视图时,每个父视图都可以绑定到子视图的事件。然后当点击发生时,它将通过链冒泡,直到适当的视图处理它。
这是一个简单的例子来展示一般的想法。我按照事件冒泡发生的顺序来呈现这个,希望它更清楚一点。
首先,ContactItemView 获取 DOM click 事件并为其触发 Backbone 事件。
//ContactItemView.js
events : {
"click .contactName" : "click"
},
click : function(evt){
this.trigger("clicked", this);
}
ContactListView 可以监听并重新发布它:
//ContactListView.js
render : function(){
var itemView = new ContactItemView();
itemView.on("clicked", this.itemClicked, this);
},
itemClicked : function(item){
this.trigger("clicked", item);
}
SidebarView 监听该事件,并且实际上知道如何处理它:
//SidebarView.js
render: function(){
var listView = new ContactListView();
this.contentView = new ContentView();
listView.on(clicked, this.contactItemClicked, this);
},
contactItemClicked : function(contactItem){
this.contentView.showMeAContact(contactItem.model); //or whatever
}
这样,您的 ContactItemView 对父视图一无所知,因此可以更加灵活。缺点是它有很多样板代码。也许其他人会有更清洁的方法,但这对我有用。
查看Backbone.Courier。它是一个轻量级的主干插件,专为您描述的那种“事件冒泡”场景而构建,使子视图可以轻松地与父母、祖父母等进行通信,而无需触发链或全局事件聚合器。