Как добавить прослушиватели событий к нескольким кнопкам, каждая из которых изменяет разные части данных

#javascript #button #addeventlistener

#javascript #кнопка #addeventlistener

Вопрос:

Я работаю над своим первым личным проектом, и я почти закончил, но я изо всех сил пытаюсь заставить некоторые кнопки работать. В моем проекте можно сохранять закладки, и есть столбец для закладок, которые являются избранными, и столбец для других сохраненных закладок. Каждая из этих кнопок соответствует элементу, извлеченному из базы данных (я использую Firestore для своей базы данных, но для этого поста я изменил его, чтобы устранить необходимость в Firestore), и, следовательно, они не жестко закодированы в HTML-файле. Когда новая закладка сохраняется, у нее есть имя (например, «Reddit»), URL («www.reddit.com «), и логическое значение для его статуса избранного (true, если это избранное, false, если в противном случае). Я хочу, чтобы у каждой закладки была связанная кнопка, которую можно щелкнуть, чтобы переместить закладку в другой столбец. Я застрял на том, как добавить прослушиватель событий к каждому элементу в базе данных, который изменяет только данные из этого одного элемента. Код приведен ниже (внизу есть больше объяснений.

Полный код можно найти здесь (включает все, что вам нужно для полного запуска программы):https://github.com/matt-manning/Bookmarker

Вот свернутая версия (все еще достаточная для самостоятельного использования):

 const bookmarkList = document.querySelector('#other-list');
const favoriteList = document.querySelector('#favorite-list');
const form = document.querySelector('#add-bookmark');

function start() {
    const db = [
        {website: 'Reddit', url: 'www.reddit.com', favorite: true},
        {website: 'Google', url: 'www.google.com', favorite: false},
        {website: 'Netflix', url: 'www.netflix.com', favorite: true},
        {website: 'YouTube', url: 'www.youtube.com', favorite: false}
    ];
    const bookmarkData = setupBookmarks(db);
    registerBookmarkEventListeners(db, bookmarkData);
}

const setupBookmarks = (data) => {
    let favoritesHTML, bookmarksHTML = '';
    const bookmarkData = [];
    if (data amp;amp; data.length) {
        data.forEach(doc => {
            const bookmarkId = Math.floor(Math.random() * 10000000);
            const bookmark = doc;
            if (bookmark.favorite) {
                favoritesHTML  = bookmarkHTML(bookmark, bookmarkId);
            } else {
                bookmarksHTML  = bookmarkHTML(bookmark, bookmarkId);
            }
            bookmarkData.push({bookmark, bookmarkId});
        })
    }
    favoriteList.innerHTML = favoritesHTML;
    bookmarkList.innerHTML = bookmarksHTML;
    return bookmarkData;
}

const bookmarkHTML = (bookmark, bookmarkId) => {
    let html = '';
    // cut for minimizing; here is a potentially relevant snippet. Full code can be found in the github link above.
    const li =
        `<li>
            <button class='btn-flat waves-light btn-small right listener' id='${bookmarkId}'>
                <i class='material-icons left'>compare_arrows</i>switch</button>
        <li>`;
    html  = li;
    return html;
}
  

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

Вот пара попыток, которые я предпринял (другие попытки можно найти по ссылке github):

 const registerBookmarkEventListeners = (data, bookmarkData) => {
    document.querySelectorAll('.listener').forEach(elem => {
        elem.addEventListener('click', e => {
            e.preventDefault();
            const bookmark = elem;
            if (bookmark.favorite) {
                bookmark.favorite = false;
            } else {
                bookmark.favorite = true;
            }
        })
    })
}

const registerBookmarkEventListeners = (data, bookmarkData) => {
    const {bookmark, bookmarkId} = bookmarkData;
    bookmarkData.forEach(item => {
        const btnElement = document.querySelector(`#${bookmarkId}`);
        btnElement.addEventListener('click', e => {
            e.preventDefault();
            if (bookmark.favorite) {
                bookmark.favorite = false;
            } else {
                bookmark.favorite = true;
            }
        })
    })
}
  

Я понимаю, почему мои вышеприведенные попытки не срабатывают. Первая даже не использует ни один из параметров, заданных с данными из базы данных. Вторая использует bookmarkId, но она не «подключается» (если это правильное слово) к данным, которые она должна изменять. Я изо всех сил пытаюсь выяснить, как заставить этот addEventListener работать.

Итак, как мне добавить прослушиватели событий к кнопкам через цикл, каждый из которых напрямую изменяет другую часть данных?

Спасибо за любую помощь.

Также, для полноты картины, вот соответствующий HTML, необходимый для запуска программы:

 <html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bookmarker</title>
    <link href="https://fonts.googleapis.com/icon?family=Material Icons" rel="stylesheet">
</head>
<body>
    <div class='row logged-in show-none'>
        <div class="col s6">
            <h5>Favorites</h5>
            <ul id='favorite-list'></ul>
        </div>
        <div class="col s6">
            <h5>Bookmarks</h5>
            <ul id='other-list'></ul>
        </div>
    </div>
    <script src='script.js'></script>
</body>
</html>
  

Ответ №1:

Если вы получаете элемент в bookmarkData.forEach(item => … тогда вы должны поместить деструктурирование в эту фигурную скобку и иметь что-то вроде

 const { bookmarkId, bookmark } = item;
  

Ответ №2:

То, как я это сделал:

  1. Передайте данные с идентификаторами в функцию registerBookmarkEventListeners.
  2. ForEach для каждого элемента.
  3. Найдите кнопку с идентификатором, соответствующим идентификатору данных, и добавьте прослушиватель.
  4. Измените избранное для этого элемента.

Ниже вы можете найти код, если вы застряли. Обратите внимание, что я изменил идентификаторы кнопок в вашем HTML-коде, добавив ‘x’ перед номером, и вам все еще нужно выяснить, как отображать элементы после изменения.

 registerBookmarkEventListeners(bookmarkData); // 1

const registerBookmarkEventListeners = (data) => {
    data.forEach(bookmark => { // 2
        document.querySelector(`#x${bookmark.bookmarkId}`).addEventListener('click', (e) => { // 3
                bookmark.bookmark.favorite = !bookmark.bookmark.favorite; // 4
                console.log(bookmark);
        })
    })
}