2012-05-10 26 views
11

¿Cuál es la mejor manera de clonar Objetos observables en Knockout para hacer un mecanismo tipo de transacción?

Por ejemplo la edición de este modelo:
¿La mejor manera de clonar observables?

var Action = function (name, ownerType, condition, expression, args) { 
    var self = this; 
    this.name = ko.observable(name); 
    this.ownerType = ko.observable(ownerType); 
    this.condition = ko.observable(condition); 
    this.expression = ko.observable(expression); 
    this.args = ko.observable(args); 
}; 

Quiero guardar el estado de ese objeto antes que el usuario va a editarlo. Y si el usuario cancelará la edición, revertir el estado del objeto.

forma más sencilla es crear otro proyecto como:

self.tempAction = new Action(action.name(), action.ownerType(), action.condition(), action.expression(), action.args()); 

Pero no estoy seguro de que es elegante solución ..

Así, alguna idea?

Respuesta

15

por lo general hacer algo como lo siguiente:

En primer lugar tengo una función que imita la función de jQuery $.extend. Rellena un objeto target con todos los valores de propiedad observable (o no observables) del objeto source.

// extends observable objects intelligently 
ko.utils.extendObservable = function (target, source) { 
    var prop, srcVal, isObservable = false; 

    for (prop in source) { 

     if (!source.hasOwnProperty(prop)) { 
      continue; 
     } 

     if (ko.isWriteableObservable(source[prop])) { 
      isObservable = true; 
      srcVal = source[prop](); 
     } else if (typeof (source[prop]) !== 'function') { 
      srcVal = source[prop]; 
     } 

     if (ko.isWriteableObservable(target[prop])) { 
      target[prop](srcVal); 
     } else if (target[prop] === null || target[prop] === undefined) { 

      target[prop] = isObservable ? ko.observable(srcVal) : srcVal; 

     } else if (typeof (target[prop]) !== 'function') { 
      target[prop] = srcVal; 
     } 

     isObservable = false; 
    } 
    return target; 
}; 

entonces tengo una función que convierte copy esencialmente el objeto a copiar en JSON y luego toma la copia JSON y construye un nuevo objeto de javascript. Esto garantiza que no se copien todos los punteros de memoria y que tenga un objeto completamente nuevo que coincida con el original. La única clave aquí es que usted tiene que pasar en una instancia vacía de un nuevo objeto (de lo contrario no tendríamos ninguna idea de qué propiedades para poblar)

// then finally the clone function 
ko.utils.clone = function(obj, emptyObj){ 
    var json = ko.toJSON(obj); 
    var js = JSON.parse(json); 

    return ko.utils.extendObservable(emptyObj, js); 
}; 

entonces usted puede usarlo de esta manera:

var tempAction = ko.utils.clone(action, new Action()); 
+0

¿No podría usar simplemente el complemento ko.mapping para mapear desde el objeto fuente original hasta el nuevo objeto objetivo? – jaffa

+0

@jaffa - sí, el complemento de mapeo sería una opción adecuada. Sin embargo, puede ser excesivo para necesidades triviales. Además, he encontrado que la función 'extendObservable' es bastante útil en situaciones en las que el complemento de mapeo no era necesario para toda la aplicación. – ericb

+0

¿Cómo funciona esto con los valores de ko.computed? Creo que usar toJSON y JSON.parse para copiar un objeto perderá todos sus valores calculados. –

Cuestiones relacionadas