微调器在获取后不会移除 api
The spinner does not remove after fetch api
我有这首歌的歌词应用程序,问题是 api 提取后旋转器没有移除。就像 javascript 没有检测到微调器已经存在,但它存在!当我调用删除函数时。
如果我删除条件:
if(spinnerHtml) {
spinnerHtml.remove();
};
只留下这个:
spinnerHtml.remove();
所以我得到这个错误:
TypeError:无法读取 null 的属性(读取 'remove')。
const form = document.querySelector("#formulario-buscar");
const artistInput = document.querySelector("#artista");
const songInput = document.querySelector("#cancion");
const searchBtn = document.querySelector("#buscar");
const divMessages = document.querySelector("#mensajes");
const divResult = document.querySelector("#resultado");
const headingSong = document.querySelector("#song-name");
function spinner() {
const spinner = document.createElement("div");
spinner.classList.add('spinner');
spinner.setAttribute('id', 'spinner');
spinner.innerHTML = `
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
`;
form.insertBefore(spinner, document.querySelector(".enviar"));
}
let spinnerExist = false;
form.addEventListener("submit", searchSong);
function searchSong(e) {
e.preventDefault();
//show spinner
if(spinnerExist === false) {
spinner();
spinnerExist = true;
};
//consult our API
const query = new API(artistInput.value, songInput.value)
query.consultApi();
}
const spinnerHtml = document.getElementById('spinner');
class API {
constructor(artist, song) {
this.artist = artist;
this.song = song;
}
async consultApi() {
const url = `https://api.lyrics.ovh/v1/${this.artist}/${this.song}`;
try {
const response = await fetch(url);
const result = await response.json();
// //when it found the lyrics it delete the spinner
if(spinnerHtml) {
spinnerHtml.remove();
};
const {lyrics} = result;
//here we assign the song lyrics to the DOM
divResult.textContent = lyrics;
headingSong.textContent = `Lyrics of ${this.song} from the artist ${this.artist}`;
} catch (error) {
console.log(error);
divMessages.textContent = error;
divMessages.classList.add("error");
setTimeout(() => {
divMessages.textContent = "";
divMessages.classList.remove("error");
}, 3000);
}
}
}
html{
min-height: 100%;
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
background-image: linear-gradient(to top, #1e3c72 0%, #1e3c72 1%, #2a5298 100%);
font-family: 'Montserrat', sans-serif;
min-height: 100%;
}
h1 {
font-weight: 400;
text-align: center;
}
h2 {
text-align: center;
}
.contenido {
background-color: white;
max-width: 1100px;
margin: 0 auto;
height: 100%;
padding: 20px;
}
@media (min-width:768px) {
.contenedor {
display: flex;
flex-wrap: wrap;
}
.contenedor > div {
flex: 1 0 50%;
}
}
.formulario-busqueda p {
text-align: center;
}
.formulario-busqueda span {
color: red;
}
.input {
margin-bottom: 1rem;
display: flex;
align-items: center;
}
.input label {
flex: 0 0 120px;
text-align: right;
margin-right: 1rem;
font-weight: 700;
text-transform: uppercase;
}
.input span {
color: red;
}
.input input[type="text"] {
height: 2.5rem;
padding: 1rem;
display: flex;
flex: 1;
}
.enviar {
text-align: center;
justify-content: center;
}
.input input[type="submit"]{
background-color: #6f86d6;
padding: .5rem 2rem;
color: white;
align-self: flex-end;
border:none;
transition: background-color .3s ease-in-out;
}
.input input[type="submit"]:hover {
cursor: pointer;
background-color: #384e9d;
}
.error {
padding: 1rem;
border: 1px solid red;
background-color: rgb(249, 121, 121);
color: white;
text-align: center;
}
#resultado {
white-space: pre-wrap;
padding: 2rem;
}
.spinner {
margin: 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner > div {
background-color: #333;
height: 100%;
width: 6px;
display: inline-block;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
@-webkit-keyframes sk-stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes sk-stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Buscador de Letras - JSModerno</title>
<link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.0/normalize.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700,900" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<main id="contenido" class="contenido">
<h1>Letras de Canciones</h1>
<div class="contenedor">
<div id="buscar" class="buscar">
<h2>Búsqueda</h2>
<p>Busca por artista y nombre:</p>
<p><span> * </span>Obligatorio</p>
<form action="#" id="formulario-buscar">
<div class="input">
<label for="artista">Artista: <span>*</span></label>
<input type="text" id="artista" placeholder="Artista">
</div>
<div class="input">
<label for="cancion">Canción: <span>*</span></label>
<input type="text" id="cancion" placeholder="Nombre Canción">
</div>
<div class="input enviar">
<input type="submit" id= "buscar" value="Buscar">
</div>
</form>
</div>
<div class="letra-resultado">
<h2 id="song-name"></h2>
<div id="resultado"></div>
</div>
<div id="mensajes"></div>
</div>
</main>
<script src="js/app.js"></script>
</body>
</html>
我认为在 类 中使用 out-of-scope 变量是一种不好的做法。 class function consultApi
似乎无法访问变量 spinnerHtml
。再次尝试使用查询选择 class function consultApi
内的元素。
我有这首歌的歌词应用程序,问题是 api 提取后旋转器没有移除。就像 javascript 没有检测到微调器已经存在,但它存在!当我调用删除函数时。
如果我删除条件:
if(spinnerHtml) {
spinnerHtml.remove();
};
只留下这个:
spinnerHtml.remove();
所以我得到这个错误: TypeError:无法读取 null 的属性(读取 'remove')。
const form = document.querySelector("#formulario-buscar");
const artistInput = document.querySelector("#artista");
const songInput = document.querySelector("#cancion");
const searchBtn = document.querySelector("#buscar");
const divMessages = document.querySelector("#mensajes");
const divResult = document.querySelector("#resultado");
const headingSong = document.querySelector("#song-name");
function spinner() {
const spinner = document.createElement("div");
spinner.classList.add('spinner');
spinner.setAttribute('id', 'spinner');
spinner.innerHTML = `
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
`;
form.insertBefore(spinner, document.querySelector(".enviar"));
}
let spinnerExist = false;
form.addEventListener("submit", searchSong);
function searchSong(e) {
e.preventDefault();
//show spinner
if(spinnerExist === false) {
spinner();
spinnerExist = true;
};
//consult our API
const query = new API(artistInput.value, songInput.value)
query.consultApi();
}
const spinnerHtml = document.getElementById('spinner');
class API {
constructor(artist, song) {
this.artist = artist;
this.song = song;
}
async consultApi() {
const url = `https://api.lyrics.ovh/v1/${this.artist}/${this.song}`;
try {
const response = await fetch(url);
const result = await response.json();
// //when it found the lyrics it delete the spinner
if(spinnerHtml) {
spinnerHtml.remove();
};
const {lyrics} = result;
//here we assign the song lyrics to the DOM
divResult.textContent = lyrics;
headingSong.textContent = `Lyrics of ${this.song} from the artist ${this.artist}`;
} catch (error) {
console.log(error);
divMessages.textContent = error;
divMessages.classList.add("error");
setTimeout(() => {
divMessages.textContent = "";
divMessages.classList.remove("error");
}, 3000);
}
}
}
html{
min-height: 100%;
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
background-image: linear-gradient(to top, #1e3c72 0%, #1e3c72 1%, #2a5298 100%);
font-family: 'Montserrat', sans-serif;
min-height: 100%;
}
h1 {
font-weight: 400;
text-align: center;
}
h2 {
text-align: center;
}
.contenido {
background-color: white;
max-width: 1100px;
margin: 0 auto;
height: 100%;
padding: 20px;
}
@media (min-width:768px) {
.contenedor {
display: flex;
flex-wrap: wrap;
}
.contenedor > div {
flex: 1 0 50%;
}
}
.formulario-busqueda p {
text-align: center;
}
.formulario-busqueda span {
color: red;
}
.input {
margin-bottom: 1rem;
display: flex;
align-items: center;
}
.input label {
flex: 0 0 120px;
text-align: right;
margin-right: 1rem;
font-weight: 700;
text-transform: uppercase;
}
.input span {
color: red;
}
.input input[type="text"] {
height: 2.5rem;
padding: 1rem;
display: flex;
flex: 1;
}
.enviar {
text-align: center;
justify-content: center;
}
.input input[type="submit"]{
background-color: #6f86d6;
padding: .5rem 2rem;
color: white;
align-self: flex-end;
border:none;
transition: background-color .3s ease-in-out;
}
.input input[type="submit"]:hover {
cursor: pointer;
background-color: #384e9d;
}
.error {
padding: 1rem;
border: 1px solid red;
background-color: rgb(249, 121, 121);
color: white;
text-align: center;
}
#resultado {
white-space: pre-wrap;
padding: 2rem;
}
.spinner {
margin: 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner > div {
background-color: #333;
height: 100%;
width: 6px;
display: inline-block;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
@-webkit-keyframes sk-stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes sk-stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Buscador de Letras - JSModerno</title>
<link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.0/normalize.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700,900" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<main id="contenido" class="contenido">
<h1>Letras de Canciones</h1>
<div class="contenedor">
<div id="buscar" class="buscar">
<h2>Búsqueda</h2>
<p>Busca por artista y nombre:</p>
<p><span> * </span>Obligatorio</p>
<form action="#" id="formulario-buscar">
<div class="input">
<label for="artista">Artista: <span>*</span></label>
<input type="text" id="artista" placeholder="Artista">
</div>
<div class="input">
<label for="cancion">Canción: <span>*</span></label>
<input type="text" id="cancion" placeholder="Nombre Canción">
</div>
<div class="input enviar">
<input type="submit" id= "buscar" value="Buscar">
</div>
</form>
</div>
<div class="letra-resultado">
<h2 id="song-name"></h2>
<div id="resultado"></div>
</div>
<div id="mensajes"></div>
</div>
</main>
<script src="js/app.js"></script>
</body>
</html>
我认为在 类 中使用 out-of-scope 变量是一种不好的做法。 class function consultApi
似乎无法访问变量 spinnerHtml
。再次尝试使用查询选择 class function consultApi
内的元素。