5

我试图回答这个问题:emberjs: add routes after app initialize()

我开始使用 Ember.Object.reopen(),以了解它是如何工作的,并且也许找到了回答上一个问题的方法。

感觉有点疑惑,不明白这段代码的行为:

jsfiddle:http: //jsfiddle.net/Sly7/FpJwT/

<script type="text/x-handlebars">
  <div>{{App.myObj.value}}</div>
  <div>{{App.myObj2.value}}</div>
  <div>{{App.myObj3.value}}</div>
</script>
App = Em.Application.create({});

App.MyObject = Em.Object.extend({value: 'initial'});

App.set('myObj', App.MyObject.create());

Em.run.later(function(){
  App.get('myObj').reopen({
    value: "reopenOnInstance"        
  }); // the template is not updated, 'initial' is still diplayed, but
  console.log(App.get('myObj').get('value')); // print 'reopenOnInstance'

  App.MyObject.reopen({
    value: "reopenOnClass"      
  });
  App.set('myObj2',App.MyObject.create()); // the template is updated and 
  console.log(App.get('myObj2').get('value')); //print 'reopenOnClass'

  App.myObj3 = App.MyObject.create(); // the template is not updated but
  console.log(App.myObj3.get('value')); // print 'reopenOnClass'

  Em.run.later(function(){
    App.get('myObj').set('value', "setWithSetter"); // the template is updated and
    console.log(App.get('myObj').get('value')); // print 'setWithSetter'

    App.get('myObj2').set('value', "setWithSetter"); // the template is updated and
    console.log(App.get('myObj2').get('value')); // print 'setWithSetter'

    App.myObj3.set('value', "setWithSetter"); // the template is not updated but
    console.log(App.myObj3.get('value')); // print 'setWithSetter'

  }, 2000);
},2000);

如果有人可以解释发生了什么,特别是为什么模板有时不更新,有时更新,以及调用reopen类,调用它和实例之间有什么区别。

4

1 回答 1

5

不是 100% 肯定,但我会尽力回答你的问题。

首先让我们看看“myObj3”。ember getter/setter 方法触发模板中的更新(它们触发内部事件,导致每个属性/观察者都知道发生了什么事)。仅手动设置一个值会更新该值,但不会触发这些事件,因此 UI 中没有任何变化。有点像使用 Mutable 列表时使用 pushObject 来确保 UI 更新。

现在让我们看看你的“重新打开”。当您在该类上重新打开时,它会按您预期的方式工作并更新基类。当您重新打开一个实例时,它实际上是在创建一个 mixin 并将其填充到对象之上。这意味着当您执行“获取”时,ember 会遍历 mixin & 对象以返回值。它找到mixin并获取对象之前的值;您实际上可以在您将获得 'foo initial' 的实例上用“return 'foo'+this._super()”替换该方法(想想您的对象有像洋葱一样的层)。如果您的对象顶部有一组 mixin,如果您直接设置某些东西,您将很难找到正确的值(但“get”会完美工作)。这导致您应该始终使用“set”的一般规则

旁注:您可以调用“getPath”而不是“get”,并且可以使用相对或绝对路径。例如 App.getPath('myObj2.value') 这将使代码更易于管理。也适用于“setPath”。

最后:打印最后一个值是因为您确实更改了值(它在其中),但用于更新 ui 的 ember 触发器从未触发,因为您从未在“myObj3”对象上调用 set。

编辑:在最新版本的 ember 中,实例上的重新打开似乎确实对对象进行了合并(如果该键已经存在)。只有在添加新内容时,mixin 才会换行。

于 2012-08-04T01:18:43.663 回答