在我的 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);
}
});
每个模型都有一个小 View ...
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;
问题一
在每次按下键时,我都会过滤集合,清空 tbody,然后呈现结果,从而为每个模型创建一个新 View 。我刚刚创建了幽灵 View ,是吗?最好适本地销毁每个 View 吗?或者我应该尝试管理我的 RowView s ...每个只创建一次,并循环遍历它们以仅呈现结果?也许是我的 CollectionView 中的一个数组?清空 tbody 后,RowViews 是否仍然具有它们的 el 还是现在为空并且需要重新呈现?
问题二,模型选择
您会注意到我在我的 RowView 中触发了一个自定义事件。我想在某处有一个详细 View 来处理该事件并显示我的整个模型。当我搜索我的列表时,如果我选择的模型保留在搜索结果中,我想保持该状态并让它保留在我的详细 View 中。一旦它不再出现在我的结果中,我将清空详细信息 View 。所以我当然需要管理一系列 View ,对吗?我考虑过一个双向链接结构,其中每个 View 都指向它的模型,每个模型都指向它的 View ......但是如果我将来要在我的模型上实现一个单例工厂,我不能将它强加给模型。 :/
那么管理这些 View 的最佳方式是什么?
最佳答案
我在玩你的问题时有点忘乎所以。
首先,我将创建一个专用集合来保存过滤后的模型,并创建一个“状态模型”来处理搜索。例如,
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);
}
});
这将被实例化为
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});
然后我会为列表和输入字段创建单独的 View :更易于维护和移动
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);
}
}
});
BaseView 允许就地更改 DOM,参见 Backbone, not "this.el" wrapping详情
实例看起来像
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);
以及现阶段搜索的演示http://jsfiddle.net/XxRD7/2/
最后,我会修改 CollectionView 以在我的渲染函数中移植行 View ,比如
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;
}
});
另一个 fiddle http://jsfiddle.net/XxRD7/3/
关于javascript - Backbone.js - 实现 "Instant"搜索的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18157333/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub