如何将事件侦听器添加到多个按钮,每个按钮修改数据的不同部分

Posted

技术标签:

【中文标题】如何将事件侦听器添加到多个按钮,每个按钮修改数据的不同部分【英文标题】:How to add event listeners to multiple buttons which each modify different parts of the data 【发布时间】:2020-12-29 07:11:36 【问题描述】:

我正在处理我的第一个个人项目,我几乎完成了,但我正在努力让一些按钮工作。我的项目是一个可以保存书签的项目,其中有一列收藏收藏的书签,一列用于保存其他已保存的书签。这些按钮每个都对应于从数据库中检索到的项目(我将 Firestore 用于我的数据库,但在这篇文章中,我已对其进行了修改以消除对 Firestore 的需求),因此不会硬编码到 html 文件中。保存新书签时,它有一个名称(例如“Reddit”)、一个网址(“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 && 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】:

我这样做的方式:

    将带有 id 的数据传递给 registerBookmarkEventListeners 函数。 ForEach 在每个元素上。 查找 id 与数据 id 匹配的按钮并添加侦听器。 更改该元素的收藏夹。

如果你卡住了,你可以在下面找到代码。请注意,我通过在数字前添加“x”更改了您的 html 代码中按钮的 ID,您仍然需要弄清楚更改后如何呈现项目。

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);
        )
    )

【讨论】:

以上是关于如何将事件侦听器添加到多个按钮,每个按钮修改数据的不同部分的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个将由事件侦听器调用的单个函数,而不是每个不同按钮的函数?

如何将侦听器附加到单选按钮

将EventListener 添加到innerHTML

如何从列表视图按钮单击将多个数据添加到数组列表?

Windows 8 应用程序将点击事件添加到超链接按钮不起作用

如何添加侦听多个按钮的动作侦听器