2012-05-10 16 views
11

Qual è il modo migliore per clonare gli oggetti osservabili in Knockout per rendere il tipo di meccanismo delle transazioni?

ad esempio la modifica di questo modello:
Il modo migliore per clonare gli osservabili?

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

voglio salvare lo stato di tale oggetto prima che l'utente sarà modificarlo. E se l'utente annullerà la modifica, lo stato dell'oggetto rollback.

modo più semplice è semplicemente creare un altro progetto come:

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

Ma io non sono sicuro che sia soluzione elegante ..

Quindi, tutte le idee?

risposta

15

Io di solito fare qualcosa di simile alla seguente:

In primo luogo ho una funzione che imita la funzione di jQuery $.extend. Compone un oggetto target con tutti i valori delle proprietà observable (o non osservabili) dell'oggetto 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; 
}; 

Poi hanno una funzione copy che converte essenzialmente l'oggetto da copiare nella JSON e poi prende la copia JSON e costruisce un nuovo oggetto JavaScript. Questo assicura che tutti i puntatori di memoria non vengano copiati e che tu abbia un oggetto nuovo di zecca che corrisponde a quello originale. L'unica chiave qui è che non deve passare in un'istanza vuota di un nuovo oggetto (altrimenti avremmo alcuna idea di cosa le proprietà per popolare)

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

è possibile utilizzare in questo modo:

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

Non potresti usare il plugin ko.mapping per mappare dall'oggetto di origine originale al nuovo oggetto di destinazione? – jaffa

+0

@jaffa - sì, il plugin di mappatura sarebbe un'opzione adatta. Tuttavia può essere eccessivo per esigenze banali. Inoltre, ho trovato la funzione 'extendObservable' abbastanza utile in situazioni in cui il plugin di mappatura non era necessario per tutta l'applicazione. – ericb

+0

Come funziona con i valori di ko.computed? Penserei che usando toJSON e JSON.parse per copiare un oggetto perderanno tutti i suoi valori calcolati. –

Problemi correlati