如何用原生JS为数组对象生成对应卡片并解决卡片重复问题
当然可以仅通过原生JS修复该问题,问题根因非常明确:
你当前的populateBooks方法逻辑是,每次调用时都会遍历整个藏书数组,把所有书籍对应的卡片直接追加到容器末尾,但是没有清理容器中已经存在的旧书籍卡片,所以每次新增书籍后,旧卡片会重复生成一遍,叠加新卡片就出现了你遇到的重复问题。
另外注意你的表单卡片也放在books-wrapper容器内,清空旧卡片时不要误删表单。
你可以选择以下任意一种方案修改:
方案1:每次渲染前清空旧卡片(改造成本最低)
直接修改populateBooks函数,在遍历渲染前先删除所有已生成的书籍卡片即可:
function populateBooks(myLib, bookView) { // 新增:清空已有书籍卡片,保留表单卡片 document.querySelectorAll('.book-card').forEach(card => card.remove()); // 原有逻辑不变 myLib.forEach((book, i) => { const card = `<div class="book-card" data-index=${i}> <div class="card-info-wrapper"> <h2>${book.title}</h2> <h3>${book.author}</h3> <h4>${book.pages} Pages</h4> <p>${book.info()}</p> <div class="button"> Remove </div> </div> </div>` const element = document.createElement('div'); element.innerHTML = card; bookView.appendChild(element.firstChild); }); };
该方案适合藏书数量不大的场景,改造成本极低。
方案2:仅渲染新增的单本藏书(性能更优)
拆分渲染逻辑,初始化时全量渲染所有藏书,新增藏书时只单独渲染新添加的那本,不需要每次遍历整个数组:
// 新增:单本藏书渲染方法 function renderSingleBook(book, index, bookView) { const card = `<div class="book-card" data-index=${index}> <div class="card-info-wrapper"> <h2>${book.title}</h2> <h3>${book.author}</h3> <h4>${book.pages} Pages</h4> <p>${book.info()}</p> <div class="button"> Remove </div> </div> </div>` const element = document.createElement('div'); element.innerHTML = card; bookView.appendChild(element.firstChild); } // 修改原有全量渲染方法,复用单本渲染逻辑 function populateBooks(myLib, bookView) { document.querySelectorAll('.book-card').forEach(card => card.remove()); myLib.forEach((book, i) => { renderSingleBook(book, i, bookView); }); }; // 修改新增藏书逻辑,不再全量渲染 function addToLibrary(e) { e.preventDefault(); const title = (document.getElementById('title')).value; const author = (document.getElementById('author')).value; const pages = (document.getElementById('pages')).value; newBook = new Book(title, author, pages); myLibrary.push(newBook); // 仅渲染新增的最后一本 renderSingleBook(newBook, myLibrary.length - 1, bookList); formDisplay(); this.reset(); console.table(myLibrary) };
该方案适合藏书数量较大的场景,不会因为数组变长出现渲染卡顿。
内容的提问来源于stack exchange,提问作者crispy
相关产品推荐
相关产品推荐

