sav*_*ger 13 javascript backbone.js
在我的Backbone应用程序中的几个地方我想对一个集合进行即时搜索,但是我很难想出实现它的最佳方法.
这是一个快速实现.http://jsfiddle.net/7YgeE/请记住,我的收藏可能包含200多个型号.
var CollectionView = Backbone.View.extend({
template: $('#template').html(),
initialize: function() {
this.collection = new Backbone.Collection([
{ first: 'John', last: 'Doe' },
{ first: 'Mary', last: 'Jane' },
{ first: 'Billy', last: 'Bob' },
{ first: 'Dexter', last: 'Morgan' },
{ first: 'Walter', last: 'White' },
{ first: 'Billy', last: 'Bobby' }
]);
this.collection.on('add', this.addOne, this);
this.render();
},
events: {
'keyup .search': 'search',
},
// Returns array subset of models that match search.
search: function(e) {
var search = this.$('.search').val().toLowerCase();
this.$('tbody').empty(); // is this creating ghost views?
_.each(this.collection.filter(function(model) {
return _.some(
model.values(),
function(value) {
return ~value.toLowerCase().indexOf(search);
});
}), $.proxy(this.addOne, this));
},
addOne: function(model) {
var view = new RowView({ model: model });
this.$('tbody').append(view.render().el);
},
render: function() {
$('#insert').replaceWith(this.$el.html(this.template));
this.collection.each(this.addOne, this);
}
});
Run Code Online (Sandbox Code Playgroud)
每个型号都有一个小视图......
var RowView = Backbone.View.extend({
tagName: 'tr',
events: {
'click': 'click'
},
click: function () {
// Set element to active
this.$el.addClass('selected').siblings().removeClass('selected');
// Some detail view will listen for this.
App.trigger('model:view', this.model);
},
render: function() {
this.$el.html('<td>' + this.model.get('first') + '</td><td>' + this.model.get('last') + '</td>');
return this;
}
});
new CollectionView;
Run Code Online (Sandbox Code Playgroud)
问题1
在每个keydown上,我过滤集合,清空tbody并渲染结果,从而为每个模型创建一个新视图.我刚创造了鬼视图,是吗?是否最好正确销毁每个视图?或者我应该尝试管理我RowView的...只创建一次,并循环遍历它们只渲染结果?我的阵列CollectionView也许?在清空之后tbody,RowViews仍然会有它们el或者现在是null并且需要重新渲染吗?
问题2,模型选择
你会注意到我正在触发我的自定义事件RowView.我希望在某个地方有一个详细视图来处理该事件并显示我的整个模型.当我搜索我的列表时,如果我选择的模型保留在搜索结果中,我想保持该状态并让它保留在我的详细视图中.一旦它不在我的结果中,我将清空详细视图.所以我当然需要管理一系列观点,对吧?我考虑过一个双重链接的结构,每个视图都指向它的模型,每个模型都指向它的视图......但如果我将来在我的模型上实现一个单独的工厂,我不能强加于模型.:/
那么管理这些视图的最佳方法是什么?
nik*_*shr 20
在玩你的问题时,我有点失望.
首先,我将创建一个专用集合来保存过滤后的模型和一个"状态模型"来处理搜索.例如,
var Filter = Backbone.Model.extend({
defaults: {
what: '', // the textual search
where: 'all' // I added a scope to the search
},
initialize: function(opts) {
// the source collection
this.collection = opts.collection;
// the filtered models
this.filtered = new Backbone.Collection(opts.collection.models);
//listening to changes on the filter
this.on('change:what change:where', this.filter);
},
//recalculate the state of the filtered list
filter: function() {
var what = this.get('what').trim(),
where = this.get('where'),
lookin = (where==='all') ? ['first', 'last'] : where,
models;
if (what==='') {
models = this.collection.models;
} else {
models = this.collection.filter(function(model) {
return _.some(_.values(model.pick(lookin)), function(value) {
return ~value.toLowerCase().indexOf(what);
});
});
}
// let's reset the filtered collection with the appropriate models
this.filtered.reset(models);
}
});
Run Code Online (Sandbox Code Playgroud)
将被实例化为
var people = new Backbone.Collection([
{first: 'John', last: 'Doe'},
{first: 'Mary', last: 'Jane'},
{first: 'Billy', last: 'Bob'},
{first: 'Dexter', last: 'Morgan'},
{first: 'Walter', last: 'White'},
{first: 'Billy', last: 'Bobby'}
]);
var flt = new Filter({collection: people});
Run Code Online (Sandbox Code Playgroud)
然后我会为列表和输入字段创建分离的视图:更容易维护和移动
var BaseView = Backbone.View.extend({
render:function() {
var html, $oldel = this.$el, $newel;
html = this.html();
$newel=$(html);
this.setElement($newel);
$oldel.replaceWith($newel);
return this;
}
});
var CollectionView = BaseView.extend({
initialize: function(opts) {
// I like to pass the templates in the options
this.template = opts.template;
// listen to the filtered collection and rerender
this.listenTo(this.collection, 'reset', this.render);
},
html: function() {
return this.template({
models: this.collection.toJSON()
});
}
});
var FormView = Backbone.View.extend({
events: {
// throttled to limit the updates
'keyup input[name="what"]': _.throttle(function(e) {
this.model.set('what', e.currentTarget.value);
}, 200),
'click input[name="where"]': function(e) {
this.model.set('where', e.currentTarget.value);
}
}
});
Run Code Online (Sandbox Code Playgroud)
BaseView允许在适当的位置更改DOM,请参阅Backbone,而不是"this.el"包装以获取详细信息
实例看起来像
var inputView = new FormView({
el: 'form',
model: flt
});
var listView = new CollectionView({
template: _.template($('#template-list').html()),
collection: flt.filtered
});
$('#content').append(listView.render().el);
Run Code Online (Sandbox Code Playgroud)
并在此阶段进行搜索演示http://jsfiddle.net/XxRD7/2/
最后,我会修改CollectionView 以在我的渲染函数中移植行视图,例如
var ItemView = BaseView.extend({
events: {
'click': function() {
console.log(this.model.get('first'));
}
}
});
var CollectionView = BaseView.extend({
initialize: function(opts) {
this.template = opts.template;
this.listenTo(this.collection, 'reset', this.render);
},
html: function() {
var models = this.collection.map(function (model) {
return _.extend(model.toJSON(), {
cid: model.cid
});
});
return this.template({models: models});
},
render: function() {
BaseView.prototype.render.call(this);
var coll = this.collection;
this.$('[data-cid]').each(function(ix, el) {
new ItemView({
el: el,
model: coll.get($(el).data('cid'))
});
});
return this;
}
});
Run Code Online (Sandbox Code Playgroud)
另一个小提琴http://jsfiddle.net/XxRD7/3/
| 归档时间: |
|
| 查看次数: |
8012 次 |
| 最近记录: |