Filtrado de datos del lado del cliente: comparación de CSS, jQuery y React | Programar Plus

Digamos que tienes una lista de 100 nombres:

<ul>
  <li>Randy Hilpert</li>
  <li>Peggie Jacobi</li>
  <li>Ethelyn Nolan Sr.</li> 
  <!-- and then some -->
</ul>

…o nombres de archivo, o números de teléfono, o lo que sea. Y desea filtrarlos del lado del cliente, lo que significa que no está realizando una solicitud del lado del servidor para buscar datos y devolver resultados. Solo desea escribir “rand” y hacer que filtre la lista para incluir “Randy Hilpert” y “Danika Randall” porque ambos tienen esa cadena de caracteres. Todo lo demás no está incluido en los resultados.

Veamos cómo podríamos hacer eso con diferentes tecnologías.

CSS puede hacerlo, con un poco de ayuda.

CSS no puede seleccionar cosas según el contenido que contienen, pero puede seleccionar atributos y los valores de esos atributos. Así que pasemos los nombres a los atributos también.

<ul>
  <li data-name="Randy Hilpert">Randy Hilpert</li>
  <li data-name="Peggie Jacobi">Peggie Jacobi</li>
  <li data-name="Ethelyn Nolan Sr.">Ethelyn Nolan Sr.</li> 
  ...
</ul>

Ahora, para filtrar esa lista por nombres que contengan “rand”, es muy fácil:

li {
  display: none;
}
li[data-name*="rand" i] {
  display: list-item;
}

Nota la i en la Línea 4. Eso significa “sin distinción entre mayúsculas y minúsculas”, lo cual es muy útil aquí.

Para hacer que esto funcione dinámicamente con un filtro <input>, necesitaremos involucrar a JavaScript para no solo reaccionar al filtro que se está escribiendo, sino también generar CSS que coincida con lo que se está buscando.

Digamos que tenemos un <style> bloque sentado en la página:

<style id="cssFilter">
  /* dynamically generated CSS will be put in here */
</style>

Podemos observar cambios en nuestra entrada de filtro y generar ese CSS:

filterElement.addEventListener("input", e => {
  let filter = e.target.value;
  let css = filter ? `
    li {
      display: none;
    }
    li[data-name*="${filter}" i] {
      display: list-item;
    }
  ` : ``;
  window.cssFilter.innerHTML = css;
});

Tenga en cuenta que estamos vaciando el bloque de estilo cuando el filtro está vacío, por lo que se muestran todos los resultados.

ver la pluma
Técnica de filtrado: CSS de Chris Coyier (@chriscoyier)
en CodePen.

Admito que es un poco extraño aprovechar CSS para esto, pero Tim Carry una vez lo llevó mucho más lejos si está interesado en el concepto.

jQuery lo hace aún más fácil.

Dado que necesitamos JavaScript de todos modos, tal vez jQuery sea una herramienta aceptable. Hay dos cambios notables aquí:

  • jQuery puede seleccionar elementos en función del contenido que contienen. Tiene una API selectora solo para esto. Ya no necesitamos el atributo extra.
  • Esto mantiene todo el filtrado en una sola tecnología.

Todavía observamos la entrada para escribir, luego, si tenemos un término de filtro, ocultamos todos los elementos de la lista y revelamos los que contienen nuestro término de filtro. De lo contrario, los revelamos todos nuevamente:

const listItems = $("li");

$("#filter").on("input", function() {
  let filter = $(this).val();
  if (filter) {
    listItems.hide();
    $(`li:contains('${filter}')`).show();
  } else {
    listItems.show();
  }
});

Se necesita más manipulación para hacer que el filtro no distinga entre mayúsculas y minúsculas que CSS, pero podemos hacerlo anulando el método predeterminado:

jQuery.expr[':'].contains = function(a, i, m) {
  return jQuery(a).text().toUpperCase()
      .indexOf(m[3].toUpperCase()) >= 0;
};

ver la pluma
Técnica de filtrado: jQuery por Chris Coyier (@chriscoyier)
en CodePen.

React puede hacerlo con estado y renderizar solo lo que necesita.

No hay una única forma de hacer esto en React, pero creo que es React-y para mantener la lista de nombres como datos (como una matriz), mapearlos y solo representar lo que necesita. Los cambios en la entrada filtran los datos en sí y React vuelve a renderizar según sea necesario.

si tenemos un names = [array, of, names], podemos filtrarlo bastante fácilmente:

filteredNames = names.filter(name => {
  return name.includes(filter);
});

Esta vez, la distinción entre mayúsculas y minúsculas se puede hacer así:

filteredNames = names.filter(name => {
  return name.toUpperCase().includes(filter.toUpperCase());
});

Entonces haríamos lo típico .map() cosa en JSX para recorrer nuestra matriz y generar los nombres.

ver la pluma
Técnica de filtrado: Reaccionar por Chris Coyier (@chriscoyier)
en CodePen.

no tengo ninguna preferencia en particular

Este no es el tipo de cosa para la que eliges una tecnología. Lo haces en cualquier tecnología que ya tengas. Tampoco creo que ningún enfoque sea particularmente más pesado que el resto en términos de deuda técnica.