2

我正在开发一个世界时间的应用程序。我有一个 ember 模型:Clock
我想time每秒更新时钟的属性。

现在,我已经start在时钟中定义了一个方法,负责更新时钟模型的时间属性。

我对此有两个问题:1.如何start从我的角度调用模型的方法 2.我可以采取更好的方法吗?

这是我的模型、视图、控制器、路由器和模板(如果你感兴趣的话):

模型:

App.Clock = DS.Model.extend({
    city: DS.attr('string'),
    country: DS.attr('string'),
    latitude: DS.attr('string'),
    longitude: DS.attr('string'),
    time: DS.attr('date'),
    order: DS.attr('number'),

    start: function() {
        var clock = this;

        var updateTime = function() {
            var timezoneService = Utilities.TimezoneService;

            timezoneService.getTimezone(clock.get('latitude'), clock.get('longitude'), function(timezone) {
                clock.set('time', timezoneService.getDateTime(timezone.offset));
            });
        };

        updateTime();

        window.setInterval(function() {
            updateTime();
        }, 1000);
    }
});

意见:

App.ClocksView = Ember.View.extend({
  templateName : 'world_clock/clocks'
});

App.ClocksNewView = Ember.View.extend({
  templateName : 'world_clock/new'
});

控制器:

App.ClocksController = Ember.ArrayController.extend({
    sortProperties: ['order']
});

App.ClocksNewController = Ember.ObjectController.extend({
    city: null,
    save: function() {
        var cityName = this.get('city');
        if(!cityName.trim()){
            return;
        }

        var locationService = Utilities.LocationService.getInstance();

        locationService.lookupLocation(cityName, function(location) {
            var city = location.city;
            var country = location.country;
            var lat = location.latitude;
            var lon = location.longitude;

            if(city && country && lat && lon) {
                var clks = App.Clock.find({ city: city });
                clks.on('didLoad', function() {
                    if(clks.get('length') === 0) {
                        var clock = App.Clock.createRecord({
                            city: location.city,
                            country: location.country,
                            latitude: location.latitude,
                            longitude: location.longitude,
                            order: 10
                        });

                        clock.save();
                    }
                });
            }
        });

        this.set('city', '');

        this.get('target').transitionTo('clocks');
    }
});

路由器:

App.Router.map(function() {
    this.resource('clocks', { path: '/' }, function() {
        this.route('new');
    });
});

App.ClocksRoute = Ember.Route.extend({
    model: function() {
        var locationService = Utilities.LocationService.getInstance();

        locationService.getLocation(function(location) {
            App.Clock.createRecord({
                city: location.city,
                country: location.country,
                latitude: location.latitude,
                longitude: location.longitude,
                order: -10
            });
        });

        return App.Clock.find();
    }
});

时钟.车把:

{{outlet}}
{{#linkTo "clocks.new"}}Add Clock{{/linkTo}}
<ul>
    {{#each controller}}
    <li>{{city}}, {{country}} - {{time}}</li>
    {{else}}
    You have not defined any clock yet.
    {{/each}}
</ul>

新的车把:

<form {{action "save" on="submit"}}>
    {{view Ember.TextField valueBinding="city" placeholder="City"}}
    <button>Save</button>
</form>
4

1 回答 1

3

如何从我的视图中调用模型的启动方法

除非在极少数情况下,从视图调用模型方法不是一个好主意。那就是说有可能。例如,您可能会使用类似 didInsertElement 的东西:

{{each controller itemViewClass="App.ClockView" emptyViewClass="App.NoClocksView"}}

App.ClockView = Ember.View.extend({
  template: Ember.Handlebars.compile("<li>{{city}}, {{country}} - {{time}}</li>"),
  didInsertElement: function() {
    var clock = this.get('content');
    clock.start();
  }
});

App.NoClocksView = Ember.View.extend({
  template: Ember.Handlebars.compile("You have not defined any clock yet.")
});

这种方法的问题在于它有点破坏封装,这意味着许多微妙的事情可能会出错。例如,如果 ember 重新使用视图以使其具有新时钟但没有运行 didInsertElement 怎么办。这就是为什么在 didInsertElement中初始化状态不是一个好主意的原因。或者如果用户导航到/离开这条路线怎么办,所以模型时钟在后台运行,然后当用户回来时,它们都会重新开始。这导致我:

我可以采取什么更好的方法吗?

可能time不应该是 的属性App.Clock。这不像您想在数据库中节省时间,对吧?一种替代方法是: -App.Clock 为时区偏移提供 computedProperty - 将 currentTime 属性添加到 clocksController - 插入 ClocksView 后,使用 setTimeout 每秒刷新 currentTime - 制作呈现特定时钟的组件(世界时钟) - 添加计算属性time到世界时钟,它在给定 currentTime 和时钟的时区偏移量的情况下计算时间。

所以是这样的:

<script type="text/x-handlebars" id="clocks">
{{outlet}}
{{#linkTo "clocks.new"}}Add Clock{{/linkTo}}
<ul>
{{#each clock in controller}}
<li>
{{world-clock city="clock.city" country="clock.country" offset="clock.offset" currentTime="currentTime"}}
</li>  
{{/each}}
</ul>
</script>

<script type="text/x-handlebars" id="components/world-clock">
  {{city}}, {{country}} - {{time}}
</script>

App.Clock = DS.Model.extend({
  city: DS.attr('string'),
  country: DS.attr('string'),
  latitude: DS.attr('string'),
  longitude: DS.attr('string'),
  order: DS.attr('number'),
  offset: function() {
    var offset;
    var service = Utilities.TimezoneService;
    service.getTimezone(this.get('latitude'), this.get('longitude'), function(zone) {
      offset = timezone.offset
    });
    return offset;
  }.property('latitude', 'longitude')
});

App.WorldClockComponent = Ember.Component.extend({
  tagName: 'li',
  time: function() {
    var service = Utilities.TimezoneService;
    return service.getDateTime(this.get('offset'));
  }.property('offset', 'currentTime');
});
于 2013-08-18T04:09:48.733 回答