【问题标题】:Array.filter() method in JavaScriptJavaScript 中的 Array.filter() 方法
【发布时间】:2020-07-01 15:51:25
【问题描述】:

我正在尝试压缩我在 JS 中关于 array.filter() 方法的代码 sn-p。我想根据啤酒的类别过滤啤酒,我已经使用下面的代码。但是,我不想像我一样重复自己,因此找到一种更简单/更短的方法来显示相同​​的代码。

<div id="filters">
  <button class="filterButton">Types of beer</button>
  <div class="filterOptions">
    <li class="filter" data-action="filter" data-filter="IPA">IPA</li>
    <li class="filter" data-action="filter" data-filter="Hefeweizen">
      Hefeweizen
    </li>
    <li class="filter" data-action="filter" data-filter="Oktoberfest">
      Oktoberfest
    </li>
    <li class="filter" data-action="filter" data-filter="European Lager">
      European Lager
    </li>
    <li class="filter" data-action="filter" data-filter="Stout">Stout</li>
    <li class="filter" data-action="filter" data-filter="Belgian Specialty Ale">
      Belgian Specialty Ale
    </li>
    <li class="filter" data-action="filter" data-filter="California Common">
      California Common
    </li>
  </div>
</div>

Javascript

function setFilters() {
  //show filters:
  document.querySelector(".filterButton").addEventListener("click", (e) => {
    document.querySelector(".filterOptions").classList.toggle("showFilters");
  });
  //event listeners:
  document
    .querySelector("[data-filter='IPA']")
    .addEventListener("click", filterIPA);
  document
    .querySelector("[data-filter='Hefeweizen']")
    .addEventListener("click", filterHefe);
  document
    .querySelector("[data-filter='Oktoberfest']")
    .addEventListener("click", filterOkt);
  document
    .querySelector("[data-filter='European Lager']")
    .addEventListener("click", filterEuro);
  document
    .querySelector("[data-filter='Stout']")
    .addEventListener("click", filterStout);
  document
    .querySelector("[data-filter='Belgian Specialty Ale']")
    .addEventListener("click", filterBelgian);
  document
    .querySelector("[data-filter='California Common']")
    .addEventListener("click", filterCalif);
  document
    .querySelector("[data-sort='alc']")
    .addEventListener("click", sortAlc);
  document.querySelector(".resetFilter").addEventListener("click", resetFilter);
}

function filterIPA() {
  console.log(allBeers);
  let ipaBeers = allBeers.filter(function (IPA) {
    return IPA.category == "IPA";
  });
  displayBeer(ipaBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterHefe() {
  console.log(allBeers);
  let hefeBeers = allBeers.filter(function (hefe) {
    return hefe.category == "Hefeweizen";
  });
  displayBeer(hefeBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterOkt() {
  console.log(allBeers);
  let oktBeers = allBeers.filter(function (okt) {
    return okt.category == "Oktoberfest";
  });
  displayBeer(oktBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterEuro() {
  console.log(allBeers);
  let euroBeers = allBeers.filter(function (euro) {
    return euro.category == "European Lager";
  });
  displayBeer(euroBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterStout() {
  console.log(allBeers);
  let stoutBeers = allBeers.filter(function (stout) {
    return stout.category == "Stout";
  });
  displayBeer(stoutBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterBelgian() {
  console.log(allBeers);
  let belgianBeers = allBeers.filter(function (belgian) {
    return belgian.category == "Belgian Specialty Ale";
  });
  displayBeer(belgianBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function filterCalif() {
  console.log(allBeers);
  let califBeers = allBeers.filter(function (calif) {
    return calif.category == "California Common";
  });
  displayBeer(califBeers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

function resetFilter() {
  location.reload();
}

【问题讨论】:

  • 标记无效。 &lt;li&gt; 元素只能是 &lt;ol&gt;&lt;ul&gt; 元素的直接子元素

标签: javascript filtering minimize


【解决方案1】:

如果我没看错,您能否创建一个通用的 filterBeer 函数来接受您要过滤的类别?

类似这样的:

function filterBeer(category) {
  console.log(allBeers);
  let beers = allBeers.filter(function (b) {
    return b.category == category;
  });
  displayBeer(beers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

【讨论】:

  • filterX 函数用作事件处理程序,您可以利用这一事实(和this)-> function filterBeer() { const category = this.dataset("filter"); ... } 然后对所有click 事件使用filterBeer
【解决方案2】:

除了变量名称和硬编码类别之外,您的所有函数都完全相同。

这是最简单的重构形式:将公共元素提取到一个函数中,并使确实的一个元素改变一个参数到该函数中。像这样:

function filterBeer(category) {
  console.log(allBeers);
  let beers = allBeers.filter(function (beer) {
    return beer.category == category;
  });
  displayBeer(beers);
  getPrices();
  document.querySelector(".filterOptions").classList.remove("showFilters");
}

然后,您可以放弃现有的每一个功能并改用它。当然,您需要编辑 click 侦听器以使用参数调用函数,而不仅仅是独立调用。像这样:

document.querySelector("[data-filter='IPA']").addEventListener("click", function() { filterBeer("IPA") });
document.querySelector("[data-filter='Hefeweizen']").addEventListener("click", function() { filterBeer("Hefeweizen") });
//etc

但是,我也注意到这里也存在冗余。 filterBeer 的参数在每种情况下都与被查询的 data-filter 完全相同。你也可以在这里做一个函数。

function addFilterClick(category) {
  document.querySelector("[data-filter='" + category + "']")
    .addEventListener("click", function() { filterBeer(category) });
}

使用此函数,您可以将 setFilters 函数简化为:

addFilterClick("IPA");
addFilterClick("Hefeweizen");
//etc

但是即使这个可以进一步简化,因为您在一系列不同的字符串上重复相同的函数调用。您可以创建一个数组并对其进行循环:

var categories = [ "IPA", "Hefeweizen", "Oktoberfest", "European Lager", ... ];
for(var i = 0; i < categories.length; i++)
  addFilterClick(categories[i]);

此时您可以去掉addFilterClick,只需将document.querySelector 线放回去,因为您只会在一个地方使用addFilterClick

【讨论】:

  • setFilters() 仅添加事件处理程序,因此标记已经存在 - 包括 data-filter 属性。为什么不直接使用已经可用的标记(可能由服务器控制)及其所有属性(订单、价值、啤酒数量……)。通过您的设置,您将需要从 JS 中的数组填充的 categories.length "empty" &lt;li&gt; 元素。如果有新啤酒,您将不得不更改两个位置(数组 + 标记),而不是仅添加新的 &lt;li data-filter="new beer" /&gt; 元素
  • @Andreas 老实说,我是一个 node.js 开发人员并且不接触 html,因此需要找出正确的查询来获取元素列表以及任何属性和功能得到data-filter - 你肯定是对的,它会更好。
  • @Klaycon 非常感谢您的帮助,我在如何使通用函数适用于每个类别时遇到了一些问题,但我现在明白了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多