Búsqueda de sitios web

knockout.js - ¿Cómo se observan las tablas hash de JavaScript en Knockout?


En mi viewmodel de Knockout, tengo algunas propiedades en las que estoy tratando de hacer que un hash sea observable. Así que en lugar de mi código previo a Knockout de

self.MyHash = {};

Ahora estoy usando:

self.MyHash = ko.observable({});

En otras partes de mi código, estoy manipulando el hash con declaraciones como estas:

// add an entry
self.MyHash()["test"] = "My Value";

// remove an entry
delete self.MyHash()["test"];

El código funciona, en el sentido de que las entradas se agregan y eliminan correctamente. Sin embargo, los cambios en la tabla hash no parecen ser detectados por las áreas del código que la están observando. Por ejemplo, este observable calculado nunca se ejecuta cuando estoy cambiando la tabla hash:

self.Querystring = ko.computed(function ()
{
    var f = [];
    $.each(self.MyHash(), function (k, v)
    {
        f.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
    });

    return (f.length > 0) ? f.join("&") : "";
});

Voy a suponer que esto se debe a que los observables de Knockout deben ser variables simples (o observableArrays), y que no está detectando los cambios subyacentes en mi tabla hash.

Si es así, ¿hay otras opciones? ¿Por qué no hay un tipo observableHash en Knockout?

Por lo que vale, mi solución alternativa es tener un observableArray de claves y una tabla hash de JavaScript normal para buscar los valores. Luego cambié mi método computado para observar el arreglo de claves en lugar de la otra variable de tabla hash que tenía antes. Solo quiero asegurarme de no estar perdiéndome la "Forma Correcta" de hacerlo en Knockout.

self.MyHashKeys = ko.observableArray();
self.MyHash = {};

self.Querystring = ko.computed(function ()
{
    var f = [];
    $.each(self.MyHashKeys(), function (index, value)
    {
        f.push(encodeURIComponent(value) + '=' + encodeURIComponent(self.MyHash[value]));
    });

    return (f.length > 0) ? f.join("&") : "";
});

Respuesta #1

Consulta el segundo ejemplo en la página del array observable. Solo haz un array de pares clave/valor:

// This observable array initially contains three objects
var anotherObservableArray = ko.observableArray([
    { name: "Bungle", type: "Bear" },
    { name: "George", type: "Hippo" },
    { name: "Zippy", type: "Unknown" }
]);

En tus ejemplos solo estás iterando (excepto para la eliminación), por lo que no hay una necesidad real de usar un diccionario real. Sería bastante fácil simplemente buscar la clave. Creo que el uso de map es en cierto modo una optimización prematura. También no está completamente en línea con la capacidad de las cadenas de consulta de admitir la misma clave varias veces.

Editar: si quieres observar el cambio de la clave o el valor en este ejemplo, también tendrías que hacer observables esas propiedades:

var anotherObservableArray = ko.observableArray([
    { name: ko.observable("Bungle"), type: ko.observable("Bear") }
]);