29

我刚开始学习 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 的创建者后,我将它作为我的主要学习资源)。

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

4

3 回答 3

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 美分:当通过 URL/直接浏览器导航进入应用程序时,为什么模型挂钩刚刚执行?

Ember 假设,如果您使用{{linkTo}}. 在您使用的场所模板{{#linkTo 'place' place}} {{place.name}} {{/linkTo}}中。您正在将一个地点对象传递给您的路线。Ember 假定这是您在执行模型钩子时会得到的同一个对象。所以从 Embers 视图中不需要调用模型钩子。因此,如果您想在使用时执行检索逻辑,请linkTo使用setupController hook.

于 2013-03-28T10:12:29.527 回答
17

强制 Ember 使用模型钩子;只需传递 id 而不是对象:

{{#link-to 'place' place.id}}
    {{place.name}}
{{/link-to}}

由于 Ember 不再知道哪个对象与给定的 id 相关,Ember 将调用模型钩子(因此数据将从服务器加载)。

于 2015-11-09T09:22:22.890 回答
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

于 2014-12-05T17:26:40.163 回答