Cómo utilizar el método Array.Filter de JavaScript para filtrar o eliminar elementos de forma selectiva de una matriz.
Primeros pasos
Para este tutorial, vamos a utilizar el marco JavaScript de pila completa de CheatCode, Joystick. Joystick reúne un marco de interfaz de usuario de front-end con un back-end de Node.js para crear aplicaciones.
Para comenzar, querremos instalar Joystick a través de NPM. Asegúrese de estar usando Node.js 16+ antes de instalar para garantizar la compatibilidad (lea este tutorial primero si necesita aprender a instalar Node.js o ejecutar varias versiones en su computadora):
Terminal
npm i -g @joystick.js/cli
Esto instalará Joystick globalmente en su computadora. Una vez instalado, vamos a crear un nuevo proyecto:
Terminal
joystick create app
Después de unos segundos, verá un mensaje desconectado de cd
en su nuevo proyecto y ejecute joystick start
:
Terminal
cd app && joystick start
Después de esto, su aplicación debería estar ejecutándose y estamos listos para comenzar.
Cableando una interfaz de usuario
Primero, antes de filtrar nuestra matriz, configuraremos una interfaz de usuario para contextualizar nuestro trabajo. Nuestro objetivo será crear una lista de álbumes de música que podamos filtrar según el género de cada álbum.
En la aplicación que acabamos de crear cuando ejecutamos joystick create app
, se creó un componente de ejemplo para nosotros en /ui/pages/index/index.js
. Abramos eso ahora y reemplacemos los contenidos existentes con el esqueleto de nuestra interfaz de usuario de filtrado.
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
const albums = [
{ id: 1, artist: 'Queens of the Stone Age', title: 'Songs for the Deaf', year: 2002, genre: 'rock' },
{ id: 2, artist: 'David Bazan', title: 'Havasu', year: 2022, genre: 'rock' },
{ id: 3, artist: 'Dwight Yoakam', title: 'This Time', year: 1993, genre: 'country' },
{ id: 4, artist: 'Sion', title: 'Sion', year: 2021, genre: 'metal' },
{ id: 5, artist: 'Every Time I Die', title: 'Low Teens', year: 2016, genre: 'metal' },
{ id: 6, artist: 'Cannonball Adderley', title: 'Somethin\' Else', year: 1958, genre: 'jazz' },
{ id: 7, artist: 'The Bad Plus', title: 'Suspicious Activity?', year: 2005, genre: 'jazz' },
{ id: 8, artist: 'Cory Hale', title: 'Soft', year: 2020, genre: 'electronic' },
{ id: 9, artist: 'Rezz', title: 'Spiral', year: 2021, genre: 'electronic' },
{ id: 10, artist: 'Autolux', title: 'Future Perfect', year: 2004, genre: 'experimental' },
];
const Index = ui.component({
state: {
filteredAlbums: albums,
},
render: ({ each, state }) => {
return `
<div>
<ul>
${each(state.filteredAlbums, (album) => `
<li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
`)}
</ul>
</div>
`;
},
});
export default Index;
Aquí, estamos escribiendo un componente usando el @joystick.js/ui
biblioteca que es parte del marco Joystick. Los componentes son funciones que devuelven una cadena de HTML que se representa en el navegador del usuario y se actualiza cada vez que hay datos dinámicos dentro el componente cambia.
Para comenzar, estamos haciendo dos cosas importantes aquí:justo debajo de nuestra importación de ui
objeto del @joystick.js/ui
paquete, estamos definiendo una matriz de objetos con cada objeto representando un álbum en nuestra lista. Hemos creado esto aquí porque necesitamos poder hacer referencia a una copia no modificada de nuestra lista (esto tendrá más sentido en un momento).
A los state
propiedad en el objeto de opciones que pasamos a nuestro ui.component()
definición, estamos configurando una propiedad filteredAlbums
al albums
formación. Esta es la configuración predeterminada valor para el filteredAlbums
propiedad en estado. El estado son datos temporales dentro de nuestro componente que solo existen hasta que se actualiza la página.
Bajando al render
función, somos return
ing una cadena de HTML que está representando un <ul></ul>
(lista desordenada) que mostrará nuestra lista de álbumes. Para enumerar esos elementos, usando la desestructuración de JavaScript en el primer argumento pasado al render
función:arrancamos el each
y state
propiedades de nuestra instancia de componente (esta instancia es el primer argumento pasado al render
función).
Dentro del HTML para nuestro <ul></ul>
etiqueta, estamos usando la interpolación de JavaScript para decir "en este punto de la cadena, inyecte este valor". El valor que queremos inyectar es el resultado de llamar al each()
función que acabamos de extraer de la instancia del componente (devuelve una cadena de HTML).
A ese each
función, pasamos una matriz de elementos, en este caso nuestro filteredAlbums
valor de state
junto con una función que se llamará para cada elemento de la matriz. Se espera que esa función devuelva una cadena de HTML para cada valor en la matriz. Aquí, cada elemento de la matriz es un album
y queremos devolver un <li></li>
(elemento de la lista) para cada álbum.
Dentro de esa función, devolvemos una cadena idéntica al return
principal para nuestro render
función, pasando nuestro <li></li>
etiqueta rellenada con las partes de nuestro álbum, utilizando la misma etiqueta de interpolación de JavaScript ${}
acabamos de aprender a inyectar valores en la cadena. El resultado final de la ejecución de este código se verá así:
<ul>
<li>Queens of the Stone Age - Songs for the Deaf (2002) <span>#rock</span></li>
<li>David Bazan - Havasu (2022) <span>#rock</span></li>
<li>Dwight Yoakam - This Time (1993) <span>#country</span></li>
...
</ul>
Ahora que tenemos la representación de nuestra lista, a continuación, queremos comenzar a cablear nuestro filtrado. Para hacerlo, primero, necesitamos tener un mecanismo por el cual realmente filtraremos nuestra lista.
Conectando una matriz para filtrar
Como insinuamos anteriormente, nuestro objetivo es filtrar nuestra matriz de álbumes por género . Para iniciar ese proceso, ahora vamos a agregar una función de método personalizado que recupera el género de cada uno de nuestros álbumes y lo llena en un <select></select>
etiqueta que usaremos para filtrar nuestra lista.
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
const albums = [
{ id: 1, artist: 'Queens of the Stone Age', title: 'Songs for the Deaf', year: 2002, genre: 'rock' },
{ id: 2, artist: 'David Bazan', title: 'Havasu', year: 2022, genre: 'rock' },
{ id: 3, artist: 'Dwight Yoakam', title: 'This Time', year: 1993, genre: 'country' },
{ id: 4, artist: 'Sion', title: 'Sion', year: 2021, genre: 'metal' },
{ id: 5, artist: 'Every Time I Die', title: 'Low Teens', year: 2016, genre: 'metal' },
{ id: 6, artist: 'Cannonball Adderley', title: 'Somethin\' Else', year: 1958, genre: 'jazz' },
{ id: 7, artist: 'The Bad Plus', title: 'Suspicious Activity?', year: 2005, genre: 'jazz' },
{ id: 8, artist: 'Cory Hale', title: 'Soft', year: 2020, genre: 'electronic' },
{ id: 9, artist: 'Rezz', title: 'Spiral', year: 2021, genre: 'electronic' },
{ id: 10, artist: 'Autolux', title: 'Future Perfect', year: 2004, genre: 'experimental' },
];
const Index = ui.component({
state: {
filteredAlbums: albums,
},
methods: {
getAlbumGenres: () => {
const genres = albums.map(({ genre }) => {
const capitalizedGenre = genre.charAt(0).toUpperCase() + genre.slice(1);
return capitalizedGenre;
});
return Array.from(new Set(genres));
},
},
render: ({ each, state, methods }) => {
return `
<div>
<select>
<option value="all">All</option>
${each(methods.getAlbumGenres(), (genre) => {
return `
<option value="${genre.toLowerCase()}">${genre}</option>
`;
})}
</select>
<ul>
${each(state.filteredAlbums, (album) => `
<li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
`)}
</ul>
</div>
`;
},
});
export default Index;
Centrándose en el methods
propiedad que agregamos a las opciones que estamos pasando a ui.component()
, aquí hemos agregado un método (una función miscelánea a la que puede llamar en un componente Joystick) llamado getAlbumGenres
.
Cuando lo llamamos, creamos una variable llamada genres
que se establece en JavaScript .map()
que utiliza la desestructuración de JavaScript para extraer el genre
propiedad de cada objeto en nuestro albums
matriz en la parte superior de nuestro archivo. Dentro del mapa, escribimos en mayúscula el nombre del género (en nuestro albums
array está en minúsculas) para mostrar en nuestra interfaz de usuario.
Una vez que tengamos capitalizedGenre
, lo devolvemos desde el .map()
. Esto debería darnos algo como esto:
['Rock', 'Rock', 'Country', 'Metal', 'Metal', 'Jazz', 'Jazz', 'Electronic', 'Electronic', 'Experimental']
Esto nos lleva en parte al camino, pero hay un problema obvio:tenemos muchos duplicados. Para evitar esto, después de que tengamos nuestra matriz en el genres
variable, de nuestro getAlbumGenres()
función usamos el new Set()
constructor de clases, pasando nuestro genres
variable. Esto nos dará un conjunto de JavaScript a cambio, que es un objeto que solo contiene valores únicos, como este:
{ 'Rock', 'Country', 'Metal', 'Jazz', 'Electronic', 'Experimental' }
Aunque puede que no parezca un objeto JavaScript tradicional (un conjunto de pares clave/valor), JavaScript lo reconoce como tal (un Conjunto es solo un tipo especial de Objeto, extendido del prototipo de Objeto principal en el lenguaje). Si bien esto nos acerca un paso más, debido a que necesitamos poder recorrer esta lista, tomamos el resultado de llamar a new Set(genres)
y pásalo directamente a Array.from()
para recuperar nuestra lista única como una matriz:
['Rock', 'Country', 'Metal', 'Jazz', 'Electronic', 'Experimental']
Volviendo a centrarnos en el render
función, podemos ver que hemos agregado en el <select></select>
etiqueta que insinuamos anteriormente. Dentro, agregamos un <option></option>
etiqueta con un valor de all
y contenido de texto de "Todos" (esto nos permitirá regresar a la lista completa desde una lista filtrada).
Justo debajo de esto, usamos el each()
función de nuevo junto con la interpolación de JavaScript para recorrer el resultado de llamar al methods.getAlbumGenres()
función que acabamos de escribir (observe que hemos agregado methods
como uno de los valores que estamos extrayendo de la instancia del componente pasado al render
función).
Por cada genre
, generamos un <option></option>
etiqueta con la versión en minúsculas del genre
para el value
atributo y el genre
en mayúscula para el contenido del texto.
Casi termino. Ahora, estamos listos para filtrar nuestra lista. Para hacerlo, agregaremos un detector de eventos en el <select></select>
etiqueta que acabamos de agregar a nuestro render
:
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
const albums = [ ... ];
const Index = ui.component({
state: {
filteredAlbums: albums,
},
methods: { ... },
events: {
'change select': (event, component) => {
const filterByGenre = event.target.value;
component.setState({
filteredAlbums: filterByGenre === 'all' ? albums : albums.filter((album) => {
return album.genre === filterByGenre;
})
});
},
},
render: ({ each, state, methods }) => {
return `
<div>
<select>
<option value="all">All</option>
${each(methods.getAlbumGenres(), (genre) => {
return `
<option value="${genre.toLowerCase()}">${genre}</option>
`;
})}
</select>
<ul>
${each(state.filteredAlbums, (album) => `
<li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
`)}
</ul>
</div>
`;
},
});
export default Index;
Tiempo para la parte importante. Aquí, hemos agregado un events
opción a nuestro ui.component()
y en él, hemos definido un detector de eventos que dice "cuando el change
el evento se detecta en cualquier select
elemento en el componente, llame a la función que se asigna aquí."
Dentro de esa función, para el primer argumento recibimos el objeto de evento DOM que se crea cuando change
ocurre un evento y el component
instancia como segundo argumento.
Antes de realizar nuestro filtro, primero nos aseguramos de seleccionar el género por el que estamos tratando de filtrar:este será el value
propiedad del <select></select>
o el event.target
donde se originó el evento y almacenarlo en el filterByGenre
variables.
A continuación, hacemos una llamada a component.setState()
pasando un objeto de propiedades que queremos modificar en el state
de nuestro componente , en este caso, filteredAlbums
. Lo que configuramos filteredAlbums
depende del valor de filterByGenre
. Si filterByGenre
está establecido en all
entonces nosotros no desea filtrar nuestra lista. Aquí, usamos un operador ternario de JavaScript para decir si el valor es 'all'
, devuelve el albums
intacto formación. De lo contrario, o bien :
queremos llamar al .filter()
método en el albums
matriz.
A albums.filter()
pasamos una función que se llama para cada elemento de la matriz. Si el valor devuelto por esa función es un booleano true
, el elemento se mantendrá en la matriz. Si el valor devuelto es un booleano false
, se filtrará fuera de la matriz. Toma, para obtener ese true
o false
valor, verificamos si el .genre
propiedad del álbum que estamos reproduciendo actualmente coincide con filterByGenre
. Si lo hace, es un guardián. Si no es así, lo tiramos.
Porque estamos pasando nuestra llamada al albums.filter()
directamente al filteredAlbums
en el objeto pasamos a component.setState()
, asumiendo que nuestro usuario no ha seleccionado el all
opción, actualizaremos filteredAlbums
en el estado para contener solo una matriz de objetos donde el genre
propiedad en cada objeto coincide con lo que se seleccionó en el <select></select>
lista de géneros.
En un componente Joystick, cambia a state
activar una nueva representación, es decir, nuestro render()
La función se volverá a llamar inmediatamente después de nuestra llamada a component.setState()
, pasando el nuevo state.filteredAlbums
valor.
¡Eso es todo! Ahora, si miramos en el navegador, deberíamos poder filtrar nuestra lista como se esperaba:
Terminando
En este tutorial, aprendimos a filtrar una matriz utilizando el método Array.Filter de JavaScript. Para contextualizar nuestro trabajo, creamos una interfaz de usuario usando el @joystick.js/ui
biblioteca del marco Joystick para ayudarnos a generar una lista de álbumes para filtrar, junto con una entrada de selección que podríamos usar para filtrar esa lista por género.