2011-06-22 23 views
13

¿Existe alguna forma mejor (integrada?) De combinar matrices observables y matrices asociativas?ko.observableArray soporte para arrays asociativos

viewModel = { 
    a: ko.observableArray(), 
    a_assoc: {}, 
    add_item: function(i) { 
     if (typeof this.a_assoc[i] == 'undefined') { 
      this.a.push(i); 
      this.a_assoc[i]=1; 
     } 
    } 
} 

viewModel.add_item('bla'); 

Respuesta

8

Por lo general, usted haría algo como esto en Knockout:

var viewModel = { 
    a: ko.observableArray(["a","b","c","d"]), 
    add_item: function() { 
     this.a.push("new" + this.a().length); 
    } 
}; 

viewModel.a_assoc = ko.dependentObservable(function() { 
    var result = {}; 
    ko.utils.arrayForEach(this.a(), function(item) { 
     result[item] = 1; 
    }); 
    return result; 
}, viewModel); 

Por lo tanto, tienen una dependentObservable que se asigna la matriz a un objeto. Tenga en cuenta que cada vez que se actualiza la matriz original, el objeto se reconstruye. Por lo tanto, es menos eficiente que el método en su publicación, pero a menos que su objeto sea sustancialmente grande, es dudoso que pueda causar un problema de rendimiento.

Muestra aquí: http://jsfiddle.net/rniemeyer/PgceN/

+1

Gracias RPN. Mi conjunto de datos crecerá a 2K así que no, no veo el rendimiento como un problema. Por cierto, ¿hay una referencia en línea en ko.utils? –

+2

Actualmente no hay documentos para utilidades. El mejor recurso actualmente es de mi blog aquí: http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html –

+0

awesome. ¡Gracias! –

1

creo que lo mejor es utilizar una matriz asociativa bajo el capó para el rendimiento. También (como lo aludió) necesita utilizar un Arreglo observable para poder rastrear los cambios (porque así es como funciona el nocaut).

Si está buscando una matriz asociativa 'nocautoria', es probable que desee una forma de rastrear los cambios en el elemento (y así afectar a las cadenas de dependencia).

http://jsfiddle.net/rz41afLq/2/

Esto es lo que se me ocurrió que se adaptaba a mis necesidades. Básicamente, almacena un par de valores clave en el observableArray y utiliza una matriz asociativa estándar para almacenar una copia con fines de búsqueda.

// VIEW MODEL 
var viewModel = { 

    // we have to use observable array to track changes 
    items: ko.observableArray([]), 

    // also use associative array for performance 
    _assoc: {}, 

    update_item: function(key, value) { 

     // use a true assoc array for performance 
     // _assoc[key] = ko.observable(value) 
     if (viewModel._assoc[key]) 
     { 
      // update observable (overwriting existing item) 
      viewModel._assoc[key].value(value); 
     } 
     else { 
      // Important: See how we wrap value with an observable to detect changes 
      this.items.push(viewModel._assoc[key] = { key: key, value: ko.observable(value) }); 
     } 
    } 
}; 

Así que guarde los perros de esta manera:

update_item('dogs', ['kim', 'abbey', 'goldie', 'rover']); 
update_item('dogs', ko.observableArray(['kim', 'abbey', 'goldie', 'rover'])); 

(La segunda sólo se requiere si usted está planeando en llamar pop() o push() en la lista de perros y quiere actualizar la interfaz de usuario Usted. por supuesto, puede llamar al update_item para actualizar completamente el artículo en cualquier momento, en cuyo caso no es necesario que se observe)

Para buscar un valor, crea dinámicamente un archivo calculado para ir a buscarlo:

var dogs = getValue('dogs'); 

A continuación, tan pronto como el valor indexado como 'perros' en los cambios de matriz asociativa luego lo observable dogs() actualizará (y pueden encadenarse). Este dogs observable se puede ligar a la UI por supuesto

var getValue = function(key) { return ko.pureComputed(function() 
{ 
    // reevaluate when item is added or removed to list 
    // not necessary if the value itself changes 
    viewModel.items();              

    var item = viewModel._assoc[key]; 
    return (item == null) ? null : item.value(); 

}, viewModel);