和Ember.Object.reopen()一起玩,为什么我有这些结果?

时间:2012-07-29 19:52:17

标签: ember.js

我试图回答这个问题: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,调用它和在实例上有什么区别。

1 个答案:

答案 0 :(得分:5)

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

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

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

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

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

编辑:在最新版本的ember中,看起来像重新打开实例会对对象进行合并(如果该键已经存在)。如果要添加新内容,mixin将仅包装。