如果图标与人相关联,那么由于人由模型表示,最好将其实现为人模型上的计算属性。您尝试将其放入控制器的意图是什么?
// person.js
export default DS.Model.extend({
icon: function() { return "person-icon-" + this.get('name'); }.property('name')
..
};
那么假设people是person的数组:
{{#each people as |person|}}
icon name: {{person.icon}}
{{/each}}
@jnfingerle 提供的替代方案有效(我假设您发现他建议您循环遍历iconPeople),但似乎要创建一个包含对象的新数组需要做很多额外的工作。图标是否依赖于只有控制器知道的任何东西?如果不是,正如我所说,为什么计算它的逻辑应该在控制器中?
把东西放在哪里是一个哲学和偏好的问题。有些人喜欢只包含来自服务器的字段的准系统模型;其他人计算模型中的状态和中间结果。有些人在控制器中放了很多东西,而另一些人则更喜欢在“服务”中具有更多逻辑的轻量级控制器。就个人而言,我支持更重的模型、更轻的控制器和服务。当然,我并不是说业务逻辑、繁重的数据转换或视图准备都应该包含在模型中。但请记住,模型代表一个对象。如果对象有一些有趣的方面,无论它来自服务器还是以某种方式计算,对我来说,将其放入模型中是很有意义的。
还要记住,控制器是紧密耦合的路由/控制器/视图关系的一部分。如果您在一个控制器中计算了一些特定于模型的东西,那么您可能必须将其添加到恰好处理相同模型的其他控制器中。然后,在不知不觉中,您正在编写控制器 mixin,它们在控制器之间共享逻辑,而这些逻辑原本不应该包含在其中。
无论如何,您说您的图标来自“不相关的数据存储”。这听起来是异步的。对我来说,这暗示它可能是一个名为PersonIcon 的子模型,它是person 模型中的belongsTo。您可以使用适用于该模型的适配器和序列化程序的正确组合来实现这一点。这种方法的好处是,在创建 person 模型时,或者当您真正需要图标时(如果您说 async: true),检索图标的所有异步性都将得到半魔法处理。
但也许您没有使用 Ember Data,或者不想麻烦您。在这种情况下,您可以考虑在路由的模型钩子中使用图标来装饰人,利用 Ember 处理异步模型解析的能力,通过执行以下操作:
model: function() {
return this.store.find('person') .
then(function(people) {
return Ember.RSVP.Promise.all(people.map(getIcon)) .
then(function(icons) {
people.forEach(function(person, i) {
person.set('icon') = icons[i];
});
return people;
})
;
})
;
}
getIcon 类似于
function getIcon(person) {
return new Ember.RSVP.Promise(function(resolve, reject) {
$.ajax('http://icon-maker.com?' + person.get('name'), resolve);
});
}
或者,如果它更简洁,您可以将图标内容拆分为 afterModel 挂钩:
model: function() { return this.store.find('person'); },
afterModel: function(model) {
return Ember.RSVP.Promise.all(model.map(getIcon)) .
then(function(icons) {
model.forEach(function(person, i) {
person.set('icon') = icons[i];
});
})
;
}
现在 Ember 将等待整个承诺解决,包括获取人物及其图标并将图标粘贴到人物身上,然后再继续。
HTH。