2012-07-29 77 views
5

我試圖回答這個問題:emberjs: add routes after app initialize()玩Ember.Object.reopen(),爲什麼我有這些結果?

我開始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有什麼區別。

回答

5

不是100%肯定,但我會盡力回答你的問題。

首先讓我們看看「myObj3」。燼getter/setter方法觸發模板中的更新(它們觸發內部事件,導致每個屬性/觀察者知道發生的事情)。只需手動設置值即可更新值,但不會觸發這些事件,因此UI中沒有任何更改。有點像當你使用可變列表你使用pushObject來確保UI更新。

現在讓我們看看你的「重新打開」。當你在類上重新打開時,它會像你期望的那樣工作並更新基類。當你重新打開一個實例時,它實際上是在創建一個混合並將它放在對象的頂部。這意味着當您執行「獲取」餘燼時,會對該對象的mixin &迭代以返回值。它發現mixin並獲取對象之前的值;實際上你可以用「return'foo'+ this._super()」替換實例上的方法來取代'foo initial'(想象你的對象具有像洋蔥一樣的圖層)。如果你的對象之上有一組mixin,那麼如果你直接設置了一些東西(但「get」可以很好地工作),你將很難找到正確的值。這導致了一般規則,即應始終使用「set」而不是直接引用。

備註:您可以調用「getPath」而不是「get」,並且可以使用相對或絕對路徑。比如App.getPath('myObj2.value'),它將使代碼更易於管理。也去「setPath」。

最後:因爲你確實改變了值(它在那裏),但是更新ui的觸發器從未被觸發,因爲你從未在「myObj3」對象上調用set。

編輯:在最新版本的燼它看起來像一個實例重新打開確實對對象(如果該密鑰已存在)合併。如果您添加新內容,mixin只會包裝。

+0

這一切都有道理。非常感謝你給我啓迪。所以如果我理解的很好,重新打開一個像我這樣做的實例,與'App.get('myObj')。value ='reopenOnInstance''有同樣的行爲吧? 我知道了getPath,方法,現在使用最新的ember,get具有相同的行爲,您可以執行'obj.get('otherObj.someProperty')'。 – 2012-08-04 08:06:31

+0

請參閱編輯。這意味着你是正確的,直接設置值就像重新打開實例一樣。但是如果你有一些綁定到那個值的東西(比如UI),Ember會拋出一個錯誤,因爲沒有使用「set」(使用[fiddler](http://jsfiddle.net/scispear/n5B5d/)來查看錯誤)。 – SciSpear 2012-08-04 13:22:54

+0

再次感謝您的編輯:)。我認爲現在答案是完整的,因爲我沒有更多的事情要闡明。 – 2012-08-04 17:36:34

相關問題