Почему мое событие click срабатывает только один раз при генерации HTML, но работает правильно при console.logging? - PullRequest
0 голосов
/ 27 января 2020

Он работает так, как я намереваюсь в консоли, и при генерации HTML, но он работает только один раз с HTML, тогда как он всегда работает с консолью. Нужно ли здесь использовать al oop и возвращать HTML таким образом? Я пробовал карту, но это не массив. Редактировать: Забыл HTML, только что добавил.

<!DOCTYPE html>
<html>
<head>
<title>Pokedex</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<h1 id="main-header">Pokedex</h1>
<div id="main-container">

</div>
<script src="index.js" type="text/javascript"></script>
</body>
</html>

Javascript

const container = document.getElementById('main-container');

function getPokemon(callback) {
const xhr = new XMLHttpRequest();
const url = 'https://pokeapi.co/api/v2/pokemon/';

xhr.onload = function() {
    if(xhr.status === 200) {
        const pokemon = JSON.parse(xhr.responseText);
        container.innerHTML+=
        pokemon.results.map((poke, index)=>{ 
            return `
                <div class='cardFront'>
                    <img src='https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${(index + 1).toString()}.png'></img>
                    <h4>${poke.name}</h4>
                </div>
            `
        }).join('');

        callback();
    }
}
xhr.open('GET', url, true);
xhr.send();
}

function cardBack() {
const endPoint = this.lastChild.previousSibling.innerText;
const xhr = new XMLHttpRequest();

xhr.onload = function() {
    if(xhr.status === 200) {
        const details = JSON.parse(xhr.responseText); 
        container.innerHTML+= `
            <div class='backSide'>
                <h4>${details.name}</h4>
                <h4>${details.types[0].type.name}</h4>
            </div>
        `
    }
}
xhr.open('GET', 'https://pokeapi.co/api/v2/pokemon/' + endPoint, true);
xhr.send();
}

getPokemon(()=>{
const cardFront = document.querySelectorAll('.cardFront');
cardFront.forEach((card)=> {
    card.addEventListener('click', cardBack);
})
});

Ответы [ 2 ]

2 голосов
/ 28 января 2020

Внутри функции обратного вызова для прослушивателя кликов вы добавляете новый код html в элемент <div> основного контейнера, используя его свойство .inner HTML. Это удалит все существующие прослушиватели событий - таким образом, щелчок будет срабатывать только один раз.

Хотя я бы порекомендовал создать новый <div> с использованием

var newDiv = document.createElement("DIV");

и добавить его в основной контейнер на

document.getElementById('main-container').appendChild(newDiv);

более простое решение в вашем случае заменяет

container.innerHTML+= `
    <div class='backSide'>
        <h4>${details.name}</h4>
        <h4>${details.types[0].type.name}</h4>
    </div>
`

на

container.insertAdjacentHTML("afterend", `
    <div class='backSide'>
        <h4>${details.name}</h4>
        <h4>${details.types[0].type.name}</h4>
    </div>
`);
0 голосов
/ 28 января 2020

Я создал версию, которая соответствует всем критериям. Запрос информации об обратной карте выполняется только после нажатия на карту и повторного нажатия на карту, чтобы вернуться на передний план. Я делаю это, собирая каждую карточку спереди и сзади внутри одного и того же div и переключая «скрытый» класс между двумя сторонами.

Я бы обычно использовал fetch () и обещания, но сохранял ваш исходный код с xhr и обратные вызовы.

CodePen здесь: https://codepen.io/edlucas/pen/xxbepjM

JS

const container = document.getElementById('main-container');
const pokeNames = [];
let loading = false;

function getPokemon(callback) {

    const xhr = new XMLHttpRequest();
    const url = 'https://pokeapi.co/api/v2/pokemon/';

    xhr.onload = function () {
        if (xhr.status === 200) {
            const pokemon = JSON.parse(xhr.responseText);
            container.innerHTML +=
                pokemon.results.map((poke, index) => {
                    const pokeName = poke.name.replace(/\s/g, "");
                    pokeNames.push(poke.name);
                    return `
                                    <div id="poke-${pokeName}" class="poke-card">
                                    <div class='cardFront'>
                                            <img src='https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${(index + 1).toString()}.png'></img>
                                            <h4>${pokeName}</h4>
                                    </div>
                                    </div>
                            `
                }).join('');

            callback();
        }
    }
    xhr.open('GET', url, true);
    xhr.send();
}

function addCardBack(pokeName, callback) {
    const xhr = new XMLHttpRequest();

    xhr.onload = function () {
        if (xhr.status === 200) {
            const details = JSON.parse(xhr.responseText);
            const pokeContainer = document.getElementById(`poke-${pokeName}`);
            pokeContainer.innerHTML += `
                            <div class='cardBack'>
                                    <h4>${details.name}</h4>
                                    <h4>${details.types[0].type.name}</h4>
                            </div>
                    `;
            callback(pokeName);
        }
        loading = false;
    }
    loading = true;
    xhr.open('GET', 'https://pokeapi.co/api/v2/pokemon/' + pokeName, true);
    xhr.send();
}

function toggleCard(pokeName) {
    const cardBack = document.querySelectorAll(`#poke-${pokeName} .cardBack`)[0];

    if (!cardBack) {
        // Prevent a second click from calling this function again before data is loaded
        if (!loading) {
            addCardBack(pokeName, (pokeName) => {
                swapCards(pokeName);
            });
        }
    } else {
        swapCards(pokeName);
    }
}

function swapCards(pokeName) {
    const cardFront = document.querySelectorAll(`#poke-${pokeName} .cardFront`)[0];
    const cardBack = document.querySelectorAll(`#poke-${pokeName} .cardBack`)[0];

    if (cardFront.classList.contains('hidden')) {
        cardFront.classList.remove('hidden');
        cardBack.classList.add('hidden');
    } else {
        cardFront.classList.add('hidden');
        cardBack.classList.remove('hidden');
    }
}

getPokemon(() => {
    pokeNames.forEach((pokeName) => {
        const card = document.getElementById(`poke-${pokeName}`);
        card.addEventListener('click', () => toggleCard(pokeName));
    })
});

CSS

.hidden {
    display: none;
}

.poke-card {
    width: 100px;
    height: 150px;
    padding: 10px;
    margin-bottom: 20px;
    border: 1px solid blue;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...