为什么不调用我的ember.js路由模型?

时间:2013-03-28 09:58:52

标签: javascript ajax json model-view-controller ember.js

我刚刚开始学习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创作者以来,我就把它作为我的主要学习资源)。

如果这不正确,或者可以做得更好,请告诉我。

3 个答案:

答案 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