在模型挂钩之后设置控制器属性

Chr*_*ini 1 ember.js ember-data ember-cli

我需要在model钩子后设置一个控制器属性.我可以想到两种方法:

model(params) {
  return this.store.findRecord('user', 1);
},

afterModel(model, transition) {
  model.get('profile').then(profile => {
    this.set('profile', profile);
  });
},

setupController(controller, model) {
  controller.set('model', model);
  controller.set('profile', this.get('profile'));
},
Run Code Online (Sandbox Code Playgroud)

另一种方法.即跳过setupController:

model(params) {
  return this.store.findRecord('user', 1);
},

afterModel(model, transition) {
  model.get('profile').then(profile => {
    this.controller.set('profile', profile);
  });
},
Run Code Online (Sandbox Code Playgroud)

两者似乎都有效.

两种方法都有任何额外的优点/缺点吗?显然,后者更短.但是在afterModel钩子中设置控制器属性是否感觉"干净" ?

编辑:之间的关系/关联userprofileasync.

小智 5

正如另一张海报指出的那样,您可以访问model.profile,但如果profile是异步关联,那么代码将不起作用:

// models/user.js
profile: belongsTo('profile', { async: true })
Run Code Online (Sandbox Code Playgroud)

原因是model.profile它将返回一个承诺而不是一个值.要解决这个问题,你可以afterModel按照你的建议使用钩子,但你需要的只是

afterModel(model, transition) {
  return model.get('profile');
},
Run Code Online (Sandbox Code Playgroud)

这将发出异步调用并暂停转换直到完成,此时profile可以model.profile像往常一样访问.如果出于某种原因,您确实想要将配置文件作为控制器属性访问以避免必须为其添加前缀model.,只需在控制器中定义别名:

profile: Ember.computed.alias('model.profile')  
Run Code Online (Sandbox Code Playgroud)

如果有多个这样的属性,那么以下应该做的工作:

return Ember.RSVP.Promise.hash(this.getProperties('profile', ...));
Run Code Online (Sandbox Code Playgroud)

您也可以在model钩子中实现这一点,尽管它的可读性稍差:

model() {
  return this.store.findRecord('user', 1) .
    then(user => user.get('profile') . 
      then(() => user)
    );
}
Run Code Online (Sandbox Code Playgroud)

这就是说,找到用户,然后当找到他的个人资料(这会导致异步请求被激活),然后当找到该用户时,从承诺返回用户,所以它被正确设置model.