我正在尝试创建一个自动完成功能,该功能从Trakt API获取电影并将前3个结果呈现在页面上。每次更改“查询”文本(来自输入)时,我都会获得新数据。但是,即使这3个型号保持不变, Ember也会重新呈现页面。如何防止这种情况发生?有没有办法添加某种检查,以查看在Handlebars模板中movie.title和movie.year是否不同?或者在控制器内进行检查,只有在不同的情况下才会设置新模型?
如果我输入“how”作为我的查询,该页面将呈现:
如果我添加't',以便我的查询变为“how t”,页面将重新呈现相同的内容,从而创建不必要的数据闪存并且相同数据再次出现:
HTML
<script type="text/x-handlebars" data-template-name="application">
<div class="hero-unit">
<h1>App</h1>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="index">
{{input value=query}}
<div class="prompt">
{{prompt}}
</div>
{{#if moviesAvailable}}
{{#each movie in movies}}
<li>{{movie.title}} ({{movie.year}})</li>
{{/each}}
{{/if}}
</script>
Javascript(IndexController中“查询”的更改会触发MovieController中“查询”的更改,提示它设置新模型)
var App;
App = Ember.Application.create();
App.Movie = DS.Model.extend({
title: DS.attr('string'),
year: DS.attr('number'),
fanart: DS.attr('string'),
poster: DS.attr('string'),
overview: DS.attr('string')
});
App.IndexController = Ember.ArrayController.extend({
needs: "movies",
movies: Ember.computed.alias("controllers.movies"),
query: '',
prompt: '',
moviesAvailable: false,
queryChanged: (function() {
var length;
length = this.get('query').length;
if (length === 0) {
this.set('moviesAvailable', false);
return this.set('prompt', 'Please type two more characters.');
} else if (length === 1) {
this.set('moviesAvailable', false);
return this.set('prompt', 'Please type one more character.');
} else {
this.set('moviesAvailable', true);
this.set('prompt', '');
return this.get('movies').set('query', this.get('query'));
}
}).observes('query')
});
App.MoviesController = Ember.ArrayController.extend({
queryChanged: (function() {
var newmodel;
newmodel = this.store.find('movie', {
query: this.get('query'),
limit: 3
});
return this.set('model', newmodel);
}).observes('query')
});
App.MovieAdapter = DS.RESTAdapter.extend({
host: 'http://api.trakt.tv/search/movies.json',
namespace: '5aa5a25cfc06d869c136725b2b29d645',
ajaxOptions: function(url, type, hash) {
hash = this._super(url, type, hash);
hash.dataType = 'jsonp';
return hash;
}
});
App.MovieSerializer = DS.RESTSerializer.extend({
normalizeHash: {
movie: function(hash) {
hash.id = hash.tmdb_id;
hash.fanart = hash.images.fanart;
hash.poster = hash.images.poster;
delete hash.images;
return hash;
}
},
normalizePayload: function(payload) {
var json;
json = {
"movie": payload
};
return json;
}
});
答案 0 :(得分:2)
问题是它们是类似的结果,但不是相同的集合。
['a', 'b', 'c'] === ['a', 'b', 'c']
是假的。它们是两个不同的集合,可能包含相同的值,看起来相似,但它们是不同的实例等。
示例:http://emberjs.jsbin.com/OxIDiVU/698/edit
如果您愿意,您可以滚动自己的集合,并手动更新记录,这样可以避免整个集合消失,并在它们是相同的项目时重新出现。但是当它们不同时,它仍然会被破坏。
watchInput: function(){
//model here is just an []
var model = this.get('model');
this.store.find('color', {
limit:10
}).then(function(results){
var len = results.get('length'),
curItem,
newItem;
for(var i = 0;i<len;i++){
curItem = model.objectAt(i);
newItem = results.objectAt(i);
if(curItem!=newItem){
if(!curItem){
model.pushObject(newItem);
} else{
model.replace(i,1,[newItem]);
}
}
}
// maybe remove additional items if it only returns 1, or 2 or even 0 for that matter.
})
}.observes('stuff'),
示例:http://emberjs.jsbin.com/OxIDiVU/697/edit
另外,只是为了它的乐趣,取决于您的服务器的速度等,您可能希望在用户输入t
,th
时撤消更改请求以减少一百万个请求,the
......
watchInput: function(){
Ember.run.debounce(this, this.slowFetch, 400);
}.observes('stuff'),
http://emberjs.jsbin.com/OxIDiVU/721/edit
P.S。尝试降低去抖率以获得乐趣,看看当你输入
时它的频率