如何在JavaScript函数中获取元素并实现书籍状态切换?
解决方案
问题根源
document.querySelector()只会匹配第一个符合选择器的元素,所以每次只能给第一个按钮绑定事件,其他按钮无法触发。- 直接在HTML模板里写
onclick="changeStatus()"无法关联到对应的book对象,因为全局函数拿不到当前点击按钮对应的书籍数据。
推荐方案:事件委托(高效且易维护)
利用事件冒泡特性,给表格tbody绑定一次事件,就能处理所有状态按钮和删除按钮的点击,无需给每个按钮单独绑定。
步骤1:修改表格模板,添加行索引标识
生成表格行时,给<tr>加上data-index属性,存储当前书籍在books数组中的索引:
function addBookToTable() { $tableBody.innerHTML = ""; books.forEach((book, index) => { // 新增index参数 const htmlBook = ` <tr data-index="${index}"> <!-- 添加索引标识 --> <td>${book.title}</td> <td>${book.author}</td> <td>${book.pages}</td> <td><button class="status-button">${book.status}</button></td> <td><button class="delete">delete</button></td> </tr> `; $tableBody.insertAdjacentHTML("afterbegin", htmlBook); }); }
步骤2:给tbody绑定事件委托
在脚本末尾添加全局事件监听,统一处理状态切换和删除逻辑:
// 给表格tbody绑定事件委托,处理所有按钮点击 $tableBody.addEventListener('click', function(e) { // 获取当前点击行的索引和对应书籍 const tr = e.target.closest('tr'); if (!tr) return; const index = parseInt(tr.dataset.index); const book = books[index]; // 处理状态切换按钮 if (e.target.classList.contains('status-button')) { book.status = book.status === 'read' ? 'not read' : 'read'; e.target.textContent = book.status; localStorage.setItem("myMangaList", JSON.stringify(books)); } // 处理删除按钮 if (e.target.classList.contains('delete')) { books.splice(index, 1); addBookToTable(); localStorage.setItem("myMangaList", JSON.stringify(books)); } });
步骤3:移除旧的单独绑定代码
把addBook函数里以下代码删掉:
// 旧的删除按钮绑定(删除) const deleteBtn = document.querySelector(".delete"); deleteBtn.addEventListener("click", function deleteBook(){ books.splice(books.indexOf(book), 1); addBookToTable(book); }) // 旧的状态按钮绑定(删除) // const myBtn = document.querySelector(".status-button"); // myBtn.addEventListener('click', function changeStatus(){ // ... // });
备选方案:生成元素时绑定闭包事件
如果不想用事件委托,也可以在生成每个按钮时,通过闭包保存当前book的引用:
function addBookToTable() { $tableBody.innerHTML = ""; books.forEach((book) => { const tr = document.createElement('tr'); tr.innerHTML = ` <td>${book.title}</td> <td>${book.author}</td> <td>${book.pages}</td> <td><button class="status-button">${book.status}</button></td> <td><button class="delete">delete</button></td> `; // 绑定状态按钮事件 const statusBtn = tr.querySelector('.status-button'); statusBtn.addEventListener('click', function() { book.status = book.status === 'read' ? 'not read' : 'read'; this.textContent = book.status; localStorage.setItem("myMangaList", JSON.stringify(books)); }); // 绑定删除按钮事件 const deleteBtn = tr.querySelector('.delete'); deleteBtn.addEventListener('click', function() { books.splice(books.indexOf(book), 1); addBookToTable(); localStorage.setItem("myMangaList", JSON.stringify(books)); }); $tableBody.appendChild(tr); }); }
这种方式需要给每个按钮单独绑定事件,书籍数量较多时性能不如事件委托,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者GhostWolf
相关产品推荐
相关产品推荐

