2012-07-29 14 views
5

yo estaba tratando de responder a esta pregunta: ¿emberjs: add routes after app initialize()Jugando con Ember.Object.reopen(), ¿por qué tengo esos resultados?

empecé a jugar con Ember.Object.reopen(), para entender cómo funciona, y tal vez encontrar una manera de responder a la pregunta anterior.

me siento un poco desconcertado, y no entiendo el comportamiento de este código:

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); 

Si alguien puede explicar lo que está pasando, sobre todo por qué el las plantillas a veces no se actualizan, a veces se actualizan, y también cuál es la diferencia entre llamar al reopen en una clase, invocarlo y en una instancia.

Respuesta

5

No estoy 100% seguro, pero intentaré responder a sus preguntas.

Primero veamos "myObj3". Los métodos getter/setter de ember activan las actualizaciones en las plantillas (activan eventos internos que hacen que cada propiedad/observador sepa que algo sucedió). El solo hecho de establecer un valor a mano actualiza el valor, pero no activará estos eventos y, por lo tanto, no cambia nada en la interfaz de usuario. Algo así como cuando usas una lista Mutable usas pushObject para asegurarte de que la UI se actualice.

Ahora veamos su "reapertura". Cuando vuelves a abrir la clase, funciona como esperarías y actualiza la clase base. Cuando vuelves a abrir una instancia, en realidad está creando una mixin y la calza encima del objeto. Esto significa que cuando haces un aspa "get" itera sobre el objeto mixin & para que el valor regrese. Encuentra que mixin y obtiene el valor antes que el objeto; en realidad puedes reemplazar el método con un "return" foo '+ this._super() "en la instancia obtendrás' foo initial '(piensa que tu objeto tiene capas como una cebolla). Si tiene un grupo de Mixin encima de su objeto, tendrá dificultades para encontrar el valor correcto si establece algo directamente (pero "obtener" funcionará perfectamente). Esto lleva a la regla general de que siempre debe usar "conjunto" en lugar de una referencia directa.

Nota al margen: Puede llamar a "getPath" en lugar de "get" y puede usar la ruta relativa o absoluta. Como App.getPath ('myObj2.value') que hará que el código sea un poco más fácil de administrar. Va para "setPath" también.

Por último: El último valor se imprime porque cambiaste el valor (está allí) pero el desencadenante de la brasa para actualizar el ui nunca se activó porque nunca llamaste a establecer el objeto "myObj3".

EDITAR: En la última versión de ember parece que la reapertura en una instancia hace una fusión en el objeto (si esa clave ya existe). La mezcla solo se ajustará si agrega contenido nuevo.

+0

Todo tiene sentido. Muchas gracias, me has iluminado. Entonces, si lo entiendo bien, volver a abrir una instancia como lo hago aquí, tiene el mismo comportamiento que con 'App.get ('myObj'). Value = 'reopenOnInstance'' ¿verdad? Conocía el método getPath, y ahora con la última brasa, el get tiene el mismo comportamiento, puedes hacer 'obj.get ('otherObj.someProperty')'. –

+0

Ver la edición. Esto significa que tiene razón, establecer el valor directamente será como volver a abrir en una instancia. Pero si tiene algo vinculante para ese valor (como la interfaz de usuario) Ember arrojará un error porque "set" no se usó (hizo un [violín] (http://jsfiddle.net/scispear/n5B5d/) para ver el error). – SciSpear

+0

Gracias de nuevo por la edición :). Creo que ahora la respuesta está completa ya que no tengo más cosas para dilucidar. –

Cuestiones relacionadas