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