共计 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 中的典型操作来遍历数组并输出名称。
我没有任何特别的偏好
这不是您选择技术的目的。您可以使用现有技术进行操作。我也不认为任何一种方法在技术债务方面都比其他方法特别重。