javascript arrays knockout.js underscore.js

javascript - Utilice underscore.js "pluck" en una matriz observable knockout



arrays knockout.js (4)

Debido a que el name es una función, ¿qué tal si pluck tu matriz original en una matriz de funciones y luego usas ko.toJS para convertirla en una matriz de cadenas?

var myArray = ko.observableArray([{ id: ko.observable(1), name: ko.observable("name1") }, { id: ko.observable(2), name: ko.observable("name2") }]); var names = _.pluck(myArray(), ''name''); console.log(ko.toJS(names)); // Output: ["name1", "name2"]

Tengo una matriz observable de objetos y quiero extraer los valores usando underscore.js

Por ejemplo:

ko.observableArray([{ id: ko.observable(1), name: ko.observable("name1") }, { id: ko.observable(2), name: ko.observable("name2") }, ...])

Y solo quiero extraer los valores dentro del objeto en lugar de todo lo observable.

¿Puedo hacer esto con solo un comando?

Lo intenté:

_.pluck(myArray(), "id()") y _.pluck(myArray(), "id"())

Pero estos devuelven una variedad de indefinidos y "id no es una función" respectivamente.

¡Gracias!


Desenvolverlo primero

_.pluck(ko.toJS(myArray), ''id'') _(ko.toJS(myArray)).pluck(''id)


Pude resolver esto usando la función "mapa":

_.map(myArray(), function(item) {return item.id()});

Pero esperaba usar desplume, ya que es el caso de uso exacto para este tipo de escenario.


Respuesta corta

Utilice _.invoke lugar de _.pluck

Mira este violín de muestra .

Respuesta larga

_.pluck(list, propertyName) funciona como está documentado:

Una versión conveniente de lo que quizás sea el caso de uso más común para el mapa: extracción de una lista de valores de propiedad.

O, como mejor explicado en lodash docs: _.pluck(collection, path)

Obtiene el valor de la propiedad de la ruta de todos los elementos en la colección.

Entonces, si haces esto:

_.pluck(myArray(), "id")

lo que obtienes es una matriz con todas las id . Y todos estos id son observables, como en los objetos de la matriz original

Pero puede usar _.invoke(list, methodName, *arguments) , que, como se documenta:

Llama al método nombrado por methodName en cada valor de la lista. Cualquier argumento adicional pasado a invocar será reenviado a la invocación del método.

o, en la versión _.invoke(collection, path, [args])

Invoca el método en la ruta en cada elemento en la colección, devolviendo una matriz de los resultados de cada método invocado. Cualquier argumento adicional se proporciona a cada método invocado. Si methodName es una función, se invoca para, y esto se enlaza a, cada elemento en la colección.

De esta forma, ejecuta cada observable y obtiene su valor como se esperaba:

_.invoke(myArray(), "id")

¡Cuidado con los modelos de vista llenos de observables!

El primer comentario a esta pregunta me ha hecho incluir este aviso:

La mejor solución es usar ko.toJS para convertir todos los observables en un modelo de vista en un objeto regular de JavaScript, con propiedades regulares. Una vez que lo hagas, subrayado o cualquier otra biblioteca, funcionará como se esperaba.

La solución _.invoke solo funciona para un único nivel de observables, como este caso. Si hubiera varios niveles de observables anidados, fallará por completo, ya que invoca una función al final de la ruta, no en cada paso de la ruta, por ejemplo, _.invoke no funcionaría para este caso:

var advices = [{ person: ko.observable({ name = ko.observable(''John'') }), advice: ko.observable(''Beware of the observables!'') }];

En este caso, solo _.invoke usar _.invoke en el primer nivel, así:

var sentences = _.invoke(advices,''advice'');

Pero esto no funcionaría:

var names = _.invoke(advices,''person.name'');

En esta llamada, solo se invocará el name , pero la person no, por lo que esto fallaría, porque la person es observable, por lo tanto, no tiene una propiedad de name .

NOTA: Lodash es otra biblioteca similar, y en su mayoría compatible con subrayado, pero mejor en algunos aspectos