【问题标题】:JavaScript issue on filtering text in html element关于过滤 html 元素中的文本的 JavaScript 问题
【发布时间】:2019-05-25 00:46:24
【问题描述】:

这几天我一直在为同一段代码苦苦挣扎......

所以对于 html 部分,我有这个:

<input type="text" id="search_immobilier_ville" name="search_immobilier[ville]">
<div class="collection" id="search-ville-collection"></div>

我有一个输入,我必须输入任何城市名称,然后我想将匹配的城市名称过滤到现有的城市数组中,如下所示:

let api_results = [['Le Moule',97152],['Lamentin',97189],...]
let ville_input = document.getElementById('search_immobilier_ville');

然后将匹配的城市显示为 div #search-ville-collection 中的元素列表。

在每个 keyup 事件上,我都需要执行这个动作,并实时更新视觉列表。

我的问题是我的过滤系统搞砸了,例如,如果我搜索“lam”,我可以得到一个名为“lamentin”的城市(通过测试),另一个只有"la" 匹配像 "capesterre-de-marie-galante"

到目前为止,我已经做到了:

// Previously filled by an API
let api_results = [[name,postalCode],[name,postalCode],...];

ville_input.addEventListener('keyup', () => {
  let value = ville_input.value.toUpperCase().trim();

  // User input
  let input_val = ville_input.value.toUpperCase().trim();

  // Filtering through var ville_input
  api_results.forEach(el => {
    if (el[0].toUpperCase().startsWith(input_val) || input_val.length >= 2 && el[0].toUpperCase().includes(input_val)) {
      result_list.style.display = 'block';

      // if city not present in the html list, add it
      if (document.getElementById(el[1]) === null) {
        $(result_list).append(`<a class="collection-item search-ville-results" id="${el[1]}"> ${el[0]} - ${el[1]} </a>`);
      }
    }
  }); // End forEach

  /* Looping through the collection child nodes to check
    if there are cities that don't match the user input */
  for (let child of result_list.children) {
    console.log(child)

    // if the user input doesn't match with an existing city in the node, delete the node
    if (!child.text.toUpperCase().includes(input_val)) {
      result_list.removeChild(child);
    }
  }

  // Highlight first element of the list
  result_list.firstElementChild.classList.add('active');

  // empty results div if user input is empty
  if (input_val == '') {
    result_list.style.display = 'none';
    result_list.innerHTML = '';
  }
});

此代码部分有效。例如,如果我输入“lam”,我应该根据我的结果集只得到一个结果,但是看看这个场景:

输入“l”:

输入“la”:

输入“lam”:

(在这里你开始看到问题)

输入“蹩脚”:

我确定我的代码有问题,但我不知道是什么问题。

【问题讨论】:

标签: javascript html arrays filter


【解决方案1】:

尝试清除您的result_list,这是您在keyup 事件中所做的第一件事。

result_list.innerHTML = '';

之后,请务必过滤您的api_results

const filteredResults = api_results.filter(result => result[0].toUpperCase().includes(input_val));
console.log(filteredResults); // Sanity check.
filteredResults.forEach(result => /* your old function. */);

【讨论】:

  • 一开始我以为清空 html 列表会对 UI 性能产生负面影响,但实际上这发生得非常快,好主意,谢谢!
【解决方案2】:

您的问题在于您用于删除无效项目的循环:

for (let child of result_list.children) {
  console.log(child)

  // if the user input doesn't match with an existing city in the node, delete the node
  if (!child.text.toUpperCase().includes(input_val)) {
    result_list.removeChild(child);
  }
}

children 返回一个实时的HTMLCollection,这意味着如果您修改它(例如,通过删除项目),它将更新,这将导致您的循环出现问题。您需要以不影响集合更改的方式浏览项目。

错误的方式:

这是循环当前行为的示例。该按钮应删除所有包含“th”的项目,但请注意它不会全部获取并需要多次点击:

document.querySelector('#removeAll').addEventListener('click', () => {
  let list = document.querySelector('#list')
  for (let item of list.children) {
    if (item.textContent.toLowerCase().includes('th')) {
      list.removeChild(item)
    }
  }
})
<button type="button" id="removeAll">Remove All</button>
<ul id="list">
  <li>Stuff</li>
  <li>Things</li>
  <li>Others</li>
  <li>More</li>
</ul>

(A)正确方法:

一种不受被删除项目影响的循环遍历集合的方法是从最后一个索引开始并向后移动:

document.querySelector('#removeAll').addEventListener('click', () => {
  let list = document.querySelector('#list')
  let index = list.children.length
  while (index--) {
    let item = list.children[index]
    if (item.textContent.toLowerCase().includes('th')) {
      list.removeChild(item)
    }
  }
})
<button type="button" id="removeAll">Remove All</button>
<ul id="list">
  <li>Stuff</li>
  <li>Things</li>
  <li>Others</li>
  <li>More</li>
</ul>

更好的方法

作为附加说明,您最好完全清除列表并使用filter 获取匹配结果,然后以这种方式更新列表。就目前而言,您正在做大量检查以查看列表是否已包含该项目、检查当前列表中是否存在无效项目等。这将影响您的 UI 性能,尤其是在低端设备上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 2021-11-29
    • 2019-09-25
    • 1970-01-01
    相关资源
    最近更新 更多