javascript - 是什么原因导致无法在 keyup 上更新数组

标签 javascript fetch keyup

我正在使用普通( Vanilla ) 以 HTML 表格的形式显示 JSON JavaScript .还有一个搜索(过滤器)功能:

class CountriesList {
  constructor() {
    this.apiURL = "https://gist.githubusercontent.com/Goles/3196253/raw/9ca4e7e62ea5ad935bb3580dc0a07d9df033b451/CountryCodes.json";
    this.countries = [];
    this.searchBox = document.querySelector('#searchBox');
    this.stringToMatch = '';
    this.tableRows = '';
  }

  // Get Items
  async getFilteredCountries() {
    const response = await fetch(this.apiURL);
    this.countries = await response.json();
    // If there is a search string, filter results
    this.stringToMatch = this.searchBox.value;
    if (this.stringToMatch.length > 0) {
      this.countries = this.countries.filter(country => {
        return country.name.toLowerCase().includes(this.stringToMatch.toLowerCase()) || country.code.includes(this.stringToMatch.toUpperCase());
      });
    }
  }

  // Render rows
  renderRows(arr, container) {
    let el = document.querySelector(container);
    el.innerHTML += arr.map(function(item) {
      return `<tr>
          <td>${item.name}</td>
          <td class="text-right">${item.code}</td>
       </tr>`
    }).join('');
  }

  async hideLoader() {
    let loader = document.querySelector('.loader');
    const action = this.countries.length > 0 ? 'add' : 'remove';
    loader.classList[action]('d-none');
  }

  async init() {
    await this.getFilteredCountries();
    await this.hideLoader();
    this.searchBox.addEventListener("keyup", this.getFilteredCountries());
    this.renderRows(this.countries, '#countries_table tbody');
  }
}

const countriesList = new CountriesList();
countriesList.init();
.box {
  position: relative;
  min-height: 90vh;
}

.loader {
  border: 4px solid #ccc;
  border-top-color: transparent;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 110px;
  left: 50%;
  margin-left: -50px;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
  <div class="box">
    <div class="search">
      <input class="my-2 form-control" id="searchBox" type="text" placeholder="Search..." value="">
    </div>
    <table class="table" id="countries_table">
      <thead>
        <tr>
          <th>Country</th>
          <th class="text-right">Code</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
    <div class="loader"></div>
  </div>
</div>

问题
脚本未能更新 countries keyup 上的数组(并再次渲染表格)。
我究竟做错了什么?

最佳答案

您的renderRows 有一些原因方法没有被调用。第一件事是在添加一个方法作为事件监听器时,你应该像这样写函数名 this.getFilteredCountries而不是 this.getFilteredCountries() .我用不同的方法分离了 API 调用,因为它应该只执行一次,并且在过滤时我们可以过滤数组。最主要的是,在使用 Class 时,我们需要绑定(bind)方法或使用 ES6 语法,否则所有类属性都将是未定义的 refer to this .剩下的部分很简单。我写了一个单独的方法updateRows()这将首先清除 innerHTML 并显示结果。希望这可以解决您的问题。

class CountriesList {
  constructor() {
    this.apiURL =
      "https://gist.githubusercontent.com/Goles/3196253/raw/9ca4e7e62ea5ad935bb3580dc0a07d9df033b451/CountryCodes.json";
    this.countries = [];
    this.searchBox = document.querySelector("#searchBox");
    this.stringToMatch = "";
    this.tableRows = "";
  }

  // Get Items
  getFilteredCountries = async () => {
    const response = await fetch(this.apiURL);
    this.countries = await response.json();
    // If there is a search string, filter results
    this.stringToMatch = this.searchBox.value;
    if (this.stringToMatch.length > 0) {
      this.countries = this.countries.filter((country) => {
        return (
          country.name
            .toLowerCase()
            .includes(this.stringToMatch.toLowerCase()) ||
          country.code.includes(this.stringToMatch.toUpperCase())
        );
      });
      this.renderRows(this.countries, "#countries_table tbody");
    }
  };

  // Render rows
  renderRows = (arr, container) => {
    let el = document.querySelector(container);
    el.innerHTML = "";
    el.innerHTML += arr
      .map(function (item) {
        return `<tr>
              <td>${item.name}</td>
              <td class="text-right">${item.code}</td>
           </tr>`;
      })
      .join("");
  };

  hideLoader = async () => {
    let loader = document.querySelector(".loader");
    const action = this.countries.length > 0 ? "add" : "remove";
    loader.classList[action]("d-none");
  };

  init = async () => {
    await this.getFilteredCountries();
    await this.hideLoader();
    this.searchBox.addEventListener("keyup", this.getFilteredCountries);
    this.renderRows(this.countries, "#countries_table tbody");
  };
}

const countriesList = new CountriesList();
countriesList.init();
.box {
  position: relative;
  min-height: 90vh;
}

.loader {
  border: 4px solid #ccc;
  border-top-color: transparent;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 110px;
  left: 50%;
  margin-left: -50px;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
<link
  href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
  rel="stylesheet"
/>
<link rel="stylesheet" href="./style.css" />
<div class="container-fluid">
  <div class="box">
    <div class="search">
      <input
        class="my-2 form-control"
        id="searchBox"
        type="text"
        placeholder="Search..."
        value=""
      />
    </div>
    <table class="table" id="countries_table">
      <thead>
        <tr>
          <th>Country</th>
          <th class="text-right">Code</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
    <div class="loader"></div>
  </div>
</div>
<script src="./script.js"></script>

关于javascript - 是什么原因导致无法在 keyup 上更新数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67435789/

相关文章:

javascript - 如何获取完整页面加载的传输大小?

javascript - 让 SmoothDivScroll 从可滚动区域的中心开始

javascript - 通过 Google Chrome 扩展将代码注入(inject) Gmail - 如何确保我的脚本在完成加载后被注入(inject)?

javascript - 按住箭头键不断触发 keyUP 事件

使用按键进行 Javascript 输入验证,获取前后值

javascript - 通过这两种不同的方法调用 jQuery 功能的优缺点是什么?

javascript - 获取 promise - 返回 500 内部服务器错误

iphone - 使用 NSPredicate 从 NSManagedObjectContect 获取准确的 NSDate

php - 获取SQL记录

javascript - 我的基于网络的 javascript 游戏对 onkeyup 事件不是很敏感。如何让程序检测所有击键而不仅仅是其中一些击键?