为啥没有调用我的 ember.js 路由模型?
Posted
技术标签:
【中文标题】为啥没有调用我的 ember.js 路由模型?【英文标题】:Why isn't my ember.js route model being called?为什么没有调用我的 ember.js 路由模型? 【发布时间】:2013-03-18 17:06:15 【问题描述】:我刚开始学习 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
是基地的 id(日本的空军基地)
4c806eabd92ea093ea2e3872
是 Foursquare 上的场地 id
当places 路由被命中时,我通过调用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 的创建者后,我将它作为我的主要学习资源)。
如果这不正确,或者可以做得更好,请告诉我。
【问题讨论】:
【参考方案1】:模型钩子上的 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 美分我自己:当通过 URL/直接浏览器导航进入应用程序时,为什么模型挂钩刚刚执行?
Ember 假设,如果您使用 linkTo
,则不一定要调用模型挂钩。在您的场所模板中,您使用#linkTo 'place' place place.name /linkTo
。您正在将一个地点对象传递给您的路线。 Ember 假定这是您在执行模型挂钩时会得到的同一个对象。 因此,从 Embers 视图中无需调用模型挂钩。因此,如果您想在使用linkTo
时执行检索逻辑,请使用setupController hook
。
【讨论】:
感谢您的解释,有助于了解事情的运作方式。这是有道理的,因为我将它传递给place
,它不会检查路线上的模型。在setupController
中,如何从url中获取place_id?
啊,抱歉,虽然我在寻找它,但还没有看到您依赖于 params 对象。我想有可能获得对参数的访问权限,但我并不容易。为什么你需要再次进行 AJAX 调用,虽然你通过了这个地方?响应中是否涉及更多细节?
查看我的更新。在 setupController 中,您还可以访问通过 linkTo 传递的模型 :-)
这应该是基本的 ember 功能,我不知道为什么 ember 创建者认为所有数据都应该在主(列表)页面中 - 它效率不高。我觉得它对所有 ember 初学者来说都很困惑。
值得注意的是,如果您将 id 而不是完整记录传递给 link-to
,则会调用模型挂钩。【参考方案2】:
强制 Ember 使用模型钩子;只需传递 id 而不是对象:
#link-to 'place' place.id
place.name
/link-to
由于 Ember 不再知道哪个对象与给定 id 相关,Ember 将调用模型挂钩(因此数据将从服务器加载)。
【讨论】:
在我看来这应该是公认的答案,它为我节省了数小时徒劳的调试。我的用例可能很常见,它访问像/groups/:group_id
这样的路由,但将属于该组的用户加载为路由的模型,而不是组本身。这样我就可以直接使用 ember 数据对用户进行分页,因为 hasMany children 的分页目前充满了恐惧和危险。
我也强烈认为这应该是公认的答案,尽管公认的答案也是正确的。只是接受的那个感觉更像是一种解决方法,当这个以更自然的余烬方式解决问题时。【参考方案3】:
基于 mavilein 的回答,但更短且适用于带有 Ember Data 的 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
【讨论】:
以上是关于为啥没有调用我的 ember.js 路由模型?的主要内容,如果未能解决你的问题,请参考以下文章
coffeescript 1.7 破坏了我的 ember.js 计算属性