问题描述
我正在使用普通(普通)JavaScript 以 HTML 表格的形式显示 JSON。还有一个搜索(过滤器)功能:
Add-AzWebAppAccessRestrictionRule `
-ResourceGroupName <my-resource-group> `
-WebAppName <my-web-app-name> `
-Name FrontDoorServiceTagRule `
-Priority 100 `
-Action Allow `
-ServiceTag AzureFrontDoor.Backend `
-HttpHeader @{'x-azure-fdid' = '<my-frontdoor-id>'}
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); }
}
问题
脚本无法在 keyup 上更新<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>
数组(并再次渲染表)。
我做错了什么?
解决方法
有一些原因导致您的 renderRows
方法没有被调用。第一件事是在添加方法作为事件侦听器时,您应该像这样编写函数名称 this.getFilteredCountries
而不是 this.getFilteredCountries()
。我用不同的方法分离了 API 调用,因为它应该只执行一次,并且在过滤时我们可以过滤数组。主要的是,在使用 Class 时,我们需要绑定方法或使用 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>
您可能需要在 keyup 上的 getFilteredCountries 之后调用您的 renderRows 函数。
,您需要在值过滤结束后调用 renderRows 函数(您可以在 getFilteredCountries 函数本身内部调用它)。