Backbone.js – 在视图中过滤和显示集合数据的正确方法

我有一个巨大的启动任务加载列表。
我想显示它们取决于选定的列表/收件箱,这样就不会有每个列表的额外负载。

window.Task = Backbone.Model.extend({}); window.TasksCollection = Backbone.Collection.extend({ model: Task, url: '/api/tasks', inbox: function() { return this.filter(function(task) { return task.get('list') == null; }); }, list: function(id) { return this.filter(function(task) { return task.get('list') == id; }); } }); window.tasks = new TasksCollection; window.TaskView = Backbone.View.extend({ tagName: 'li', template: _.template($('#item-template').html()), initialize: function() { _.bindAll(this, 'render', 'close'); this.model.bind('change', this.render); this.model.view = this; }, render: function() { $(this.el).html(this.template(this.model.toJSON())); this.setContent(); return this; }, }); window.TasksView = Backbone.View.extend({ el: '#todo-list', collection: tasks, initialize: function() { _.bindAll(this, 'render'); this.collection.bind('reset', this.render); this.collection.fetch(); }, render: function() { var t = this; $(t.el).html(''); this.collection.each(function(task) { var view = new TaskView({ model:task }); $(t.el).append( view.render().el ); }); return this; }, }); window.Nicetask = Backbone.Router.extend({ routes: { '': 'inbox', '/inbox': 'inbox', '/list/:id': 'list', }, initialize: function() { _.bindAll(this, 'inbox', 'list'); window.tasksView = new TasksView; }, inbox: function() { tasks.reset( tasks.inbox() ); }, list: function(id) { tasks.reset( tasks.list(id) ); } }); 

这个代码可以工作,但是reset()函数会从任务集合中删除实际列表中的其他任务。 而在另一条路线上,任务收集是空的。

有没有合理的方法来实现这一目标? 感谢任何想法。

ps:骨干新手


UPDATE

Thx的@sled和@ibjhb的评论,这里是工作解决scheme的片段。

 window.TasksView = Backbone.View.extend({ el: '#todo-list', collection: Backbone.Collection.extend(), initialize: function() { _.bindAll(this, 'render', 'addOne', 'addAll'); this.collection.bind('add', this.addOne); this.collection.bind('reset', this.render); }, render: function(data) { $(this.el).html(''); _.each(data, function(task) { this.addOne(task); }, this); return this; }, addOne: function(task) { var view = new TaskView({ model:task }); $(this.el).append( view.render().el ); }, }); window.Nicetask = Backbone.Router.extend({ routes: { '': 'inbox', '/inbox': 'inbox', '/today': 'today', '/list/:id': 'list', }, initialize: function() { _.bindAll(this, 'inbox', 'today'); window.tasksView = new TasksView; window.menuView = new MenuListView; tasks.fetch(); }, inbox: function() { tasksView.render( tasks.inbox() ); }, today: function() { tasksView.render( tasks.today() ); }, list: function(id) { tasksView.render( tasks.list(id) ); } }); 

我想你需要使用另一个集合。 例如,在您的收件箱中,执行以下操作:

 inbox: function(){ currentCollection = new TasksCollection(tasks.inbox()); } 

我没有testing过,但是当你做.reset(); 您将删除所有模型并加载传入的模型。

@sled在您发布的代码中存在拼写错误,请参阅内嵌评论。 你把这个作为一个项目发布在某个地方吗?

 // add models add: function(models, options) { // TYPO: next line was missing, so single models not handled. models = _.isArray(models) ? models.slice() : [models]; var self = this; models = _.filter(models, this.filter); // return if no models exist // TYPO: returned undefined, so was not chainable if(models.length == 0) { return this; } // actually add the models to the superset this.superset.add(models, options); return this; }, // remove models remove: function(models, options) { // TYPO: next line was missing, so single models not handled. models = _.isArray(models) ? models.slice() : [models]; // remove model from superset this.superset.remove(_.filter(_.filter(models, function(cm) { // TYPO: not 'm != null', causes error to be thrown return cm != null; }), this.filter), options); // TYPO: missing return so not chainable return this; }, 

对您的解决scheme有一个快速的修改,您正在使用

 $(this.el).html(''); 

我的理解是你的视图和相关的事件绑定将仍然存在于浏览器内存中,所以理想情况下需要在TaskView上使用view.remove()来正确清除事件绑定以及html。


这是一个稍微不同的答案,因为我一直在寻找类似问题的解决scheme,希望这可能对别人有帮助。

我的问题: – 通过模型的属性过滤完整的集合。 例如。 用户单击模型视图,获取(某些)属性列表,select一个属性过滤集合只显示具有相同值的属性。

我正在采取的路线是从视图调用集合的方法,在我的情况下,视图是特定于模型,所以:

 this.model.collection.myFilter(attr,val); 

其中attr是与集合关联的模型的属性,然后在filter类似的东西

 myFilter: function(attr, val){ var groupByAttr = this.groupBy(function(article){ var res = (val === undefined)? true : (article.get(attr) == val); article.set({selected:res}); return res; }); return groupByAttr; } 

我已经使用._groupBy,因为这返回2个数组(积极/消极),可能是有用的。 通过设置模式属性“select”,并绑定到这个模型视图,我可以很容易地切换显示或隐藏视图的类。

如果(val === undefined)被添加为通过调用没有值的相同方法来清除filter的简单方法。