对el.dataset使用带变量的循环

时间:2018-03-03 19:53:22

标签: javascript loops

我正在创建一系列过滤器,它目前是“丑陋的代码”。我想从数组中输出所有过滤器,但我无法弄清楚如何将变量赋给元素的dataset属性。 (你会看到代码对于每个过滤器都是完全相同的,除了他们正在过滤的东西)。

任何人都可以帮我告诉我如何实现这一目标吗?

function filterList() {
  const itemsNode = document.querySelectorAll(".js-filterable");
  const items = Array.from(itemsNode);

  const filterBrand = document.querySelector(".js-filter-brand");
  const filterState = document.querySelector(".js-filter-state");
  const filterCity = document.querySelector(".js-filter-city");
  const filterOwner = document.querySelector(".js-filter-owner");
  const filtered = document.querySelector(".js-filtered");

  let filterValue;
  let results;

  // Listen for filter changes

  if (filterBrand) {
    filterBrand.addEventListener("input", function(filtered, filterValue) {
      filterValue = this.value;

      if (filterValue === "all") {
        let results = items;
        outputResults(results);
      } else {
        let results = items.filter(item => item.dataset.brand === filterValue);
        outputResults(results);
      }
    });
  }

  if (filterState) {
    filterState.addEventListener("input", function(filtered, filterValue) {
      filterValue = this.value;

      if (filterValue === "all") {
        let results = items;
        outputResults(results);
      } else {
        let results = items.filter(item => item.dataset.state === filterValue);
        outputResults(results);
      }
      
    });
  }

  if (filterCity) {
    filterCity.addEventListener("input", function(filtered, filterValue) {
      filterValue = this.value;

      if (filterValue === "all") {
        let results = items;
        outputResults(results);
      } else {
        let results = items.filter(item => item.dataset.city === filterValue);
        outputResults(results);
      }
    });
  }

  if (filterOwner) {
    filterOwner.addEventListener("input", function(filtered, filterValue) {
      filterValue = this.value;

      if (filterValue === "all") {
        let results = items;
        outputResults(results);
      } else {
        let results = items.filter(item => item.dataset.owner === filterValue);
        outputResults(results);
      }
    });
  }

  // Update filtered list

  function outputResults(results) {
    while (filtered.firstChild)
      filtered.removeChild(filtered.firstChild);
    results.forEach(function(result) {
      filtered.appendChild(result);
    });
  }
}

2 个答案:

答案 0 :(得分:0)

我想你可以从这样的事情开始:

const passThru = (x) => true;

// Return a filter function using the given property name 
const filterPropName = (propName, filterValue) => filterValue === "all" ?
        passThru : 
        ({dataset}) => dataset[propName] === filterValue;

// ...

function createListener (propName) {
    return () => {
      const filterValue = this.value;
      const results = items.filter(filterPropName(propName, filterValue));
      outputResults(results);       
    }
}

if (filterBrand) {
    filterBrand.addEventListener("input", createListener("brand"));
}

if (filterState) {
    filterState.addEventListener("input", createListener("state"));
}

// Etc.

答案 1 :(得分:0)

看起来你只想让它成为DRYer:

function filterList() {

  const itemsNode     = document.querySelectorAll(".js-filterable");
  const items         = Array.from(itemsNode);
  const filterClasses = ['brand', 'state', 'city', 'owner']

  filterClasses.forEach(filterClass => {
    const filtered = document.querySelector(`.js-filter-${filterClass}`);

    if (filtered) {
      filtered.addEventListener("input", function(filtered, filterValue) {

        filterValue = this.value;         // <-- why overwrite the param?
        let results;
        if (filterValue === "all")
          results = items;
        else
          results = items.filter(item => item.dataset[filterClass] === filterValue);
          
        outputResults(results);
      });
    }
  })
}


// Update filtered list
function outputResults(results) {
  const filteredItems = document.querySelector(".js-filtered");

  while (filteredItems.firstChild)
    filteredItems.removeChild(filteredItems.firstChild);

  results.forEach(result => filteredItems.appendChild(result));
}

特别注意:

  • filterClasses = ['brand', 'state', 'city', 'owner']用于迭代已知的类名
  • 使用item.dataset[filterClass]变量用于设置数据值