如何在sessionStorage中存储多个图书对象以避免覆盖?
如何在sessionStorage中存储多个图书对象而不被覆盖?
哥们,你遇到的问题其实很典型——sessionStorage是键值对式的存储,同一个键对应的新值会直接覆盖旧值,所以你现在每次点击书签都只存了单个图书对象,之前的自然就被冲掉了。要实现多图书保存,我们得把图书放在数组里管理,每次添加时先取出已有数组、加入新图书,再把更新后的数组存回去。
先看你代码里的几个小问题:
- 事件监听里用到的
bookStorage定义在循环末尾,这会导致事件触发时变量还没定义(或者拿到的是最后一次循环的对象,因为作用域问题); - 循环里的
i没有用let声明,会变成全局变量,所有事件监听里的i最终都会指向循环结束的最后一个值。
下面是修改后的核心代码,我给你标了关键点:
try { const responseData = await sendHttpRequest( 'GET', "https://www.googleapis.com/books/v1/volumes?q=" + search ); const listOfBooks = responseData; console.log(listOfBooks); // 循环里的i要加let,确保每次循环都是独立的作用域 for (let i=0; i < listOfBooks.items.length; i++) { console.log(listOfBooks.items[i]); const postEl = document.importNode(template.content, true); // 先定义当前图书的对象,放在事件监听前面,确保事件能拿到正确的图书数据 const bookStorage = { id: listOfBooks.items[i].id, title: listOfBooks.items[i].volumeInfo.title, author: listOfBooks.items[i].volumeInfo.authors, desc: listOfBooks.items[i].volumeInfo.description, // 用可选链+默认值处理没有图片的情况,避免报错 img: listOfBooks.items[i].volumeInfo.imageLinks?.thumbnail || "resources/css/img/unavailable.png" }; // 书签点击事件 const target = postEl.querySelector('.icon-bookmark'); target.addEventListener('click', () => { // 1. 取出已保存的图书数组,没有的话初始化空数组 let savedBooks = JSON.parse(sessionStorage.getItem('bookStorage')) || []; // 2. 可选:检查当前图书是否已经收藏,避免重复添加 const isAlreadySaved = savedBooks.some(book => book.id === bookStorage.id); if (!isAlreadySaved) { // 添加新图书到数组 savedBooks.push(bookStorage); // 3. 把更新后的数组转成JSON字符串存回sessionStorage sessionStorage.setItem('bookStorage', JSON.stringify(savedBooks)); console.log('图书已收藏!当前收藏列表:', savedBooks); } else { console.log('这本图书已经在你的收藏里啦~'); } }); // 下面的DOM渲染代码优化,避免重复查询DOM const idEl = postEl.querySelector('.id'); const titreEl = postEl.querySelector('.titre'); const authorEl = postEl.querySelector('.author'); const descEl = postEl.querySelector('.desc'); const imgEl = postEl.querySelector('img'); idEl.textContent = 'id: '+ listOfBooks.items[i].id; titreEl.textContent = 'Titre: '+ listOfBooks.items[i].volumeInfo.title; authorEl.textContent = 'Auteur: '+ listOfBooks.items[i].volumeInfo.authors; descEl.textContent ='Description: '+ listOfBooks.items[i].volumeInfo.description; imgEl.src = bookStorage.img; // 直接用上面定义好的img值 if (descEl.textContent.length > 200) { descEl.textContent = descEl.textContent.substring(0,200); } listElement.append(postEl); } } catch (error) { alert(error.message); } btnRechercher.addEventListener('click', fetchBooks, false);
核心思路解释:
- 用数组管理多个图书:sessionStorage只能存字符串,所以我们把图书数组序列化成JSON字符串存储,每次添加时先反序列化取出数组,更新后再序列化存回去;
- 解决作用域问题:循环里的
i用let声明,确保每个循环迭代都有独立的作用域,事件监听能拿到当前循环的图书对象; - 避免重复收藏:用
Array.some()检查数组里是否已有相同id的图书,防止重复添加; - 容错处理:用可选链操作符
?.处理图书没有图片链接的情况,避免抛出错误。
另外要注意,sessionStorage的存储上限大概是5MB左右,所以不要存太多大体积的图书数据哦~
内容的提问来源于stack exchange,提问作者Hermann Ouré
相关产品推荐
相关产品推荐

