我刚刚开始学习Ember.js(购买了PeepCode截屏视频),并且从中学习非常顺利,但在尝试编写我的第一个Ember应用程序时遇到了问题。
这是(嵌套的)路线映射:
App.Router.map(function () {
this.resource('bases', { path: '/' }, function () {
this.resource('base', { path: ':base_id' }, function () {
this.resource('places', function () {
this.resource('place', { path: ':place_id' });
});
});
});
});
这允许这样的网址:domain.com /#/ yokota-ab-japan / places / 4c806eabd92ea093ea2e3872
yokota-ab-japan
是基地(日本空军基地)的身份证明
4c806eabd92ea093ea2e3872
是Foursquare上场地的ID
当地点路线被击中时,我通过调用foursquare api设置数据,遍历JSON以创建App.Place对象数组,并返回该数组。
App.PlacesRoute = Ember.Route.extend({
model: function () {
var placesData = Ember.A();
$.getJSON('https://api.foursquare.com/v2/venues/search?ll=35.744771,139.349456&query=ramen&client_id=nnn&client_secret=nnn&v=20120101',
function (data) {
$.each(data.response.venues, function (i, venues) {
placesData.addObject(App.Place.create({ id: venues.id, name: venues.name, lat: venues.location.lat, lng: venues.location.lng }));
});
});
return placesData;
}
});
这似乎运作良好。我使用这个模板显示placesData数组:
<script type="text/x-handlebars" data-template-name="places">
<div>
{{#each place in controller}}
{{#linkTo 'place' place}}
{{place.name}}
{{/linkTo}}
{{/each}}
</div>
{{outlet}}
</script>
linkTo
指向单个地点的链接,我想在其中显示有关地点的更多详细信息。这是我设置的路线,用于提取有关单个地点的数据,填充单个App.Place对象,然后将其返回:
App.PlaceRoute = Ember.Route.extend({
model: function (params) {
console.log('place route called');
var place;
$.getJSON('https://api.foursquare.com/v2/venues/' + params.place_id + '?client_id=nnn&client_secret=nnn',
function (data) {
var v = data.response.venue;
place = App.Place.create({ id: v.id, name: v.name, lat: v.location.lat, lng: v.location.lng });
});
return place;
}
});
我的问题是,PlaceRoute
在用户点击指向该链接的链接时未被调用,但在此路由刷新页面时会调用它。
根据PeepCode Ember.js的截屏视频(在视频中约12:25),它表示“控制器很少会调用数据,路由对象会处理”,所以我认为我在调整我的ajax时是正确的在路线上打电话(我在网上看过很多不同的教程,但是自从Peepcode咨询了Ember.js创作者以来,我就把它作为我的主要学习资源)。
如果这不正确,或者可以做得更好,请告诉我。
答案 0 :(得分:49)
模型钩子上的Ember文档:
“您可以实现将URL转换为模型的钩子 路线“。
这解释了为什么只在页面刷新时调用模型钩子。但这让很多人感到困惑:-)。所以,在这种情况下,这不是正确的钩子。我认为你应该在这种情况下使用setupController钩子。试试这个:
App.PlaceRoute = Ember.Route.extend({
setupController: function (controller, model) {
console.log('place route called');
var place;
$.getJSON('https://api.foursquare.com/v2/venues/' + model.get('place_id') + '?client_id=nnn&client_secret=nnn',
function (data) {
var v = data.response.venue;
place = App.Place.create({ id: v.id, name: v.name, lat: v.location.lat, lng: v.location.lng });
});
controller.set("model", place);
}
});
自己额外增加2美分:当通过网址/直接浏览器导航输入应用时,为什么模型挂钩刚执行?
Ember假设,如果使用{{linkTo}}
,则不必调用模型钩子。在您的地点模板中,您使用{{#linkTo 'place' place}} {{place.name}} {{/linkTo}}
。您正在将一个位置对象传递给您的路线。 Ember假设这是与执行模型钩子时相同的对象。因此,从Embers View中无需调用模型钩子。因此,即使您使用linkTo
也要执行检索逻辑,请使用setupController hook
。
答案 1 :(得分:17)
强制Ember使用模型钩子;只是传递id而不是对象:
{{#link-to 'place' place.id}}
{{place.name}}
{{/link-to}}
由于Ember不再知道哪个对象与给定的id相关,Ember将调用模型钩子(因此数据将从服务器加载)。
答案 2 :(得分:3)
基于mavilein的答案,但更短,适用于Ember数据的Ember CLI ...
import Ember from 'ember';
export default Ember.Route.extend({
setupController: function( controller, model ) {
controller.set( "model", this.store.fetch( 'place', model.id ) );
},
});
另请注意,fetch方法仅适用于Ember Data 1.0.0-beta.12。
http://emberjs.com/api/data/classes/DS.Store.html#method_fetch