客户端过滤数据比较CSSjQuery和React

56次阅读

共计 1985 个字符,预计需要花费 5 分钟才能阅读完成。

假设您有 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 中的典型操作来遍历数组并输出名称。

我没有任何特别的偏好

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

正文完
 0