假设您有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不能根据它们包含的内容来选择项目,但是可以根据属性和这些属性的值进行选择(利用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;
}

注意第5行的字母“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;
});

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

图片描述

我承认利用CSS做到这一点很奇怪。

jQuery使得它更容易

既然我们仍然需要JavaScript,也许jQuery是可以接受的工具。这里有两个值得注意的变化:

  • jQuery 可以根据项目包含的内容来选择项目。为此,它具有选择器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;
};

图片描述

在React中可以使用状态跟Filter函数做到这一点

在React中没有做到这一点的真正方法,但我认为将名称列表保留为数据(如Array),映射它们并仅呈现所需内容是React-y。输入中的更改会过滤数据本身,并在需要时重新渲染React。

如果有一个names = [array, of, names],我们可以很容易地对其进行过滤:

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

这次,可以这样区分大小写:

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

然后,我们将执行.map()JSX中的典型操作来遍历数组并输出名称。

图片描述

我没有任何特别的偏好

这不是您选择技术的目的。您可以使用现有技术进行操作。我也不认为任何一种方法在技术债务方面都比其他方法特别重。


聪明的汤姆
557 声望23 粉丝