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