Как выполнить делегирование событий в объектно-ориентированном JS? - PullRequest
0 голосов
/ 03 апреля 2019
  1. У меня проблемы с захватом динамически создаваемых элементов DOM, и
  2. Я не знаю, где должно происходить делегирование последующего события щелчка (т. Е. В моем основном файле .js или внутри класса пользовательского интерфейса).

Этот объектно-ориентированный учебный проект отправляет асинхронные HTTP-запросы, используя fetch, в Punk API и извлекает список пива на основе поискового запроса пользователя.Выходные данные не жестко запрограммированы, но innerHTML списка динамически создается из данных API внутри класса с именем UI.

В app.js я выполняю обещания и использую ui.paint () для отображения пива на странице.

У каждого пива есть кнопка «купить», которая также создается динамически.

Я хочу захватить все кнопки, пройтись по ним, прикрепить событие щелчка.

Я пробовал:

  1. захват кнопок в app.js с помощью queryselectorAll - не работает, возвращает пустой список узлов - этот селектор должен иметьбыл поднят, и во время вызова кнопки явно еще не существуют - НАХОДИТСЯ НЕСКОЛЬКО СПЕЦИАЛЬНЫХ СПОСОБОВ решить эту проблему и дождаться возвращения данных API и создания новых элементов?(примечание: как только у меня будет список пива, я могу получить полный список узлов с помощью querySelectorAll в консоли браузера ...)

  2. Я также попытался обернуть queryselectorAll внутри функции ивызовите эту функцию внутри функции события click, которая обрабатывает обещания.Это тоже не сработало.

  3. Я пытался поместить событие в app.js, а также в класс прототипов пользовательского интерфейса (который выглядел аккуратнее), но ни один из них не работал.

app JS
const ui = new UI();

document.getElementById('submit-button- name').addEventListener('click', (e) => {
e.preventDefault();

const newBeer = new Beer();

newBeer.getByName()
    .then(beerResult => {
        ui.paint(beerResult);
    })
    .catch(err => {
        console.log(err)
    });
});

const buyBtns = document.querySelectorAll('#buy-btn');

buyBtns.forEach((buyBtn) => {
   buyBtn.addEventListener('click', (e) => {
      ui.addToCart(e)
   });  
});
then here is the UI class, trying to pick up the event (I'm trying to grab the button that's in the last <a> tag of the innerHTML and push it in a cart array which I would later display on a separate page). 
class UI {
constructor() {
    this.productRow = document.getElementById('products-row');
} 

paint(beerResult) {
    let output = '';

    beerResult.forEach(beer => {
        output += 
        `<div class="card">
            <img id="beer-card-img" src="${beer.image_url}" alt="beer-image" class="card-image-top">
            <div class="card-body">
                <h5 class="card-title">${beer.name}</h5>
                <h6 class="tagline">${beer.tagline}.</h6>
                <p id="description" class="card-text">${beer.description}</p>
                <p id="abv" class="card-text">ABV: ${beer.abv}</p>
                <p id="ibu" class="card-text">IBU: ${beer.ibu}</p>
                <p id="ph" class="card-text">PH: ${beer.ph}</p>
                <p id="first-brewed" class="card-text">First brewed: ${beer.first_brewed}</p>
                <a href="#" class="btn btn-outline-dark btn-sm">See details</a>
                <a href="#" id="buy-btn" class="btn btn-danger btn-sm">Buy</a>
            </div>
        </div>`
    });

    // console.log(output);

    this.productRow.innerHTML = output;
}

addToCart(e) {

    let cart = [];

    if (e.target.parentElement.parentElement.classList.contains('card')) {
        cart.push(e.target.parentElement.parentElement)
    }

    console.log(cart);
}

}

Прямо сейчас, когда я нажимаю «Купить», ничего не происходит.Я хочу, чтобы пиво помещалось в массив (в виде объектов) для последующего отображения на отдельной странице.

Спасибо за ваше терпение, время и советы!

1 Ответ

0 голосов
/ 04 апреля 2019
  • Имеет смысл создавать прослушиватель событий при создании кнопки.Поэтому я бы поместил прослушиватель событий в класс пользовательского интерфейса.

  • Если вы используете document.createElement() для создания кнопки, вы можете сразу присоединить обработчик.Вам не нужно querySelector()

  • Поскольку функция addToCart также находится в пользовательском интерфейсе, вы можете вызвать эту функцию и сразу передать объект beer

Это упрощенный пример кода:

class UI {

  paint(beerResult) {

    for(let b of beerResult) {
        let card = document.createElement("card")
        let buyButton = document.createElement("button")

        card.appendChild(buyButton)

        buyButton.addEventListener("click", (e) => {
            this.addToCart(b)
        })

        this.productRow.appendChild(card)
    }
  }

  addToCart(b) {
      console.log("added this beer to the cart: " + b.description)
  }
}

Приложение js

let ui = new UI()
ui.paint([{description:"a nice beer"},{description:"some beer"}])

А вот рабочий JSFiddle

...