客户端数据过滤:比较 CSS、jQuery 和 React

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您的旅程每个阶段提供云产品。立即开始使用 200 美元的免费信用额度!

假设您有一个包含 100 个名称的列表

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

…或者文件名、电话号码,或任何其他内容。您想在客户端对它们进行过滤,这意味着您不会向服务器发出请求来搜索数据并返回结果。您只需键入“rand”,它就会将列表过滤为包含“Randy Hilpert”和“Danika Randall”,因为它们都包含该字符串。列表中所有其他名称都不会出现在结果中。

让我们看看如何使用不同的技术来做到这一点。

CSS 可以做到,不过需要一些帮助。

CSS 无法根据内容选择元素,但它可以根据属性及其值进行选择。因此,我们将名称也移到属性中。

<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>

现在,要过滤包含“rand”的名称列表,这非常容易

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

请注意第 4 行的 i。它表示“不区分大小写”,这对这种情况非常有用。

要使用过滤器 <input> 使其动态工作,我们需要让 JavaScript 参与进来,不仅要对过滤器输入进行响应,还要生成与搜索内容匹配的 CSS。

假设我们在页面上有一个 <style>

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

我们可以监视过滤器输入的变化并生成该 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;
});

请注意,当过滤器为空时,我们清空了样式块,因此显示所有结果。

查看 CodePen 上的示例
过滤技术:CSS
,由 Chris Coyier (@chriscoyier) 创建。
CodePen 上。

我承认利用 CSS 来做这件事有点奇怪,但 Tim Carry 曾经把它做得更进一步,如果您有兴趣了解这个概念,可以看看。

jQuery 使其变得更加容易。

既然我们无论如何都需要 JavaScript,jQuery 可能是一个可接受的工具。这里有两个显著的变化

  • jQuery 可以根据内容选择项目。它有一个专门用于此的 selector API。我们不再需要额外的属性了。
  • 这将所有过滤操作集中在单一技术中。

我们仍然监视输入的键入操作,然后如果有过滤项,我们将隐藏所有列表项并显示包含过滤项的项。否则,我们将再次显示所有项。

const listItems = $("li");

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

与 CSS 相比,使过滤器不区分大小写需要更多调整,但我们可以通过覆盖默认方法来实现。

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

查看 CodePen 上的示例
过滤技术:jQuery
,由 Chris Coyier (@chriscoyier) 创建。
CodePen 上。

React 可以通过状态和仅渲染所需内容来实现。

在 React 中没有一种绝对正确的方法来做到这一点,但我认为,将名称列表作为数据(例如数组)保存,并对它们进行映射,然后仅渲染所需内容是 React 式的做法。输入中的更改会过滤数据本身,React 会根据需要重新渲染。

如果我们有 names = [array, of, names],我们可以轻松地对其进行过滤。

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

这次,不区分大小写的操作可以这样完成

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

然后,我们将在 JSX 中使用典型的 .map() 方法遍历数组并输出名称。

查看 CodePen 上的示例
过滤技术:React
,由 Chris Coyier (@chriscoyier) 创建。
CodePen 上。

我没有特别的偏好

这不是您选择技术的地方。您将在您已经使用的任何技术中使用它。我认为,就技术债务而言,任何一种方法都没有明显比其他方法更重。