问题描述
我有一些物品.我想跟踪当前的选择.当用户单击集合中的其他项目时,我想指出该项目已选中,并显示所选项目的详细信息.将此视为具有详细信息视图的列表(例如典型的电子邮件客户端).
I have a collection of items. I would like to keep track of the current selection. When the user clicks on a different item in the collection, I want to indicate that the item is selected and display the details of the selected item. Think of this as a list with a detail view (like a typical email client).
主从布局的示例(源):
Example of a master-detail layout (source):
我目前有类似的东西(用CoffeeScript编写,模板使用 haml-coffee ):
I currently have something like this (written in CoffeeScript, templates use haml-coffee):
class Collections.Items extends Backbone.Collection
model: Models.Item
setCurrentSelection: (id)->
# what to do here? Is this even the right way to do it?
getCurrentSelection: ->
# what to do here? Is this even the right way to do it?
class Views.ItemsPage extends Backbone.View
list_template: JST['items/list']
details_template: JST['items/details']
events:
'click .item': 'updateSelection'
initialize: (options)->
@collection = options.collection
render: ->
$('#items_list').html(@list_template(collection: @collection.toJSON())) # not sure if this is how to render a collection
$('#item_details').html(@details_template(item: @collection.currentSelection().toJSON())) # how to implement currentSelection?
@
updateSelection: (event)->
event.preventDefault()
item_id = $(event.currentTarget).data('id')
# mark the item as selected
# re-render using the new selection
# templates/items/list.hamlc
%ul
- for item in @collection
%li{data:{id: item.id}, class: ('selected' if item.selected?)} # TODO: How to check if selected?
= item.name
# templates/items/details.hamlc
%h2= @item.name
推荐答案
即使说我的CoffeeScript有点生锈"对我来说也太多了.但是我仍然会尽力在js中尽力解释.
even saying "my CoffeeScript is a bit rusty" is too much for me. But i'll still attempt to explain as best as i can in js.
首先,骨干方法是将模型保留为REST资源文档的表示形式. (服务器端-持久数据).
First the backbone way is to keep models as a representation of a REST resource document. (server side - persisted data).
客户端表示逻辑应遵循视图.记住在详细信息部分中可见的列表项是该特定视图的工作.向明细视图模型发起更改请求是项目列表的工作.
Client side presentation logic should stick to views. to remember which list item is visible in in the details part is job of the that specific view. initiating change request for details view model is job of the list of items.
理想的方法是为列表和详细信息使用两个单独的视图. (您还可以更进一步一些,并在列表视图中查看每个项目.
the ideal way is to have two separate views for list and details. (you can also go a bit more ahead and have a view for every item in the list view.
父视图
var PageView = Backbone.View.extend({
initialize: function() {
//initialize child views
this.list = new ItemListView({
collection : this.collection //pass the collection to the list view
});
this.details = new ItemDetailView({
model : this.collection.at(1) //pass the first model for initial view
});
//handle selection change from list view and replace details view
this.list.on('itemSelect', function(selectedModel) {
this.details.remove();
this.details = new ItemDetailView({
model : selectedModel
});
this.renderDetails();
});
},
render: function() {
this.$el.html(this.template); // or this.$el.empty() if you have no template
this.renderList();
this.renderDetails();
},
renderList : function(){
this.$('#items_list').append(this.list.$el); //or any other jquery way to insert
this.list.render();
},
renderDetails : function(){
this.$('#item_details').append(this.details.$el); //or any other jquery way to insert
this.details.render();
}
});
列表视图
var ItemListView = Backbone.View.extend({
events : {
'click .item': 'updateSelection'
},
render: function() {
this.$el.html(this.template);
this.delegateEvents(); //this is important
}
updateSelection : function(){
var selectedModel;
// a mechanism to get the selected model here - can be same as yours with getting id from data attribute
// or you can have a child view setup for each model in the collection. which will trigger an event on click.
// such event will be first captured by the collection view and thn retriggerd for page view to listen.
this.trigger('itemSelect', selectedModel);
}
});
详细信息视图
var ItemDetailView = Backbone.View.extend({
render: function() {
this.$el.html(this.template);
this.delegateEvents(); //this is important
}
});
如果您不重用视图,则不会通过路由保留状态.在这种情况下,您需要具有全局状态/事件保存机制.像下面这样-
This won't persist the state through routes if you don't reuse your views. in that case you need to have a global state/event saving mechanism. somthing like following -
window.AppState = {};
_.extend(window.AppState, Backbone.Events);
//now your PageView initilize method becomes something like this -
initialize: function() {
//initialize child views
this.list = new ItemListView({
collection : this.collection //pass the collection to the list view
});
var firstModel;
if(window.AppState.SelectedModelId) {
firstModel = this.collection.get(window.AppState.SelectedModelId);
} else {
firstModel = this.collection.at(1);
}
this.details = new ItemDetailView({
model : firstModel //pass the first model for initial view
});
//handle selection change from list view and replace details view
this.list.on('itemSelect', function(selectedModel) {
window.AppState.SelectedModelId = selectedModel.id;
this.details.remove();
this.details = new ItemDetailView({
model : selectedModel
});
this.renderDetails();
});
}
编辑
在列表视图中处理选定的类(突出显示).请参阅评论以供参考.
列表视图模板-
<ul>
<% _.each(collection, function(item, index){ %>
<li data-id='<%= item.id %>'><%= item.name %></li>
<% }); %>
</ul>
在内部列表视图中添加以下方法-
inside list view add following method -
changeSelectedHighlight : function(id){
this.$(li).removeClass('selected');
this.$("[data-id='" + id + "']").addClass('selected');
}
只需在updateViewion方法和PageView初始化期间调用此方法.
simply call this method from updateSelection method and during PageView initialize.
this.list.changeSelectedHighlight(firstModel.id);
这篇关于如何组织具有特定选择的骨干网收藏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!