You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在sessionStorage中存储多个图书对象以避免覆盖?

如何在sessionStorage中存储多个图书对象而不被覆盖?

哥们,你遇到的问题其实很典型——sessionStorage是键值对式的存储,同一个键对应的新值会直接覆盖旧值,所以你现在每次点击书签都只存了单个图书对象,之前的自然就被冲掉了。要实现多图书保存,我们得把图书放在数组里管理,每次添加时先取出已有数组、加入新图书,再把更新后的数组存回去。

先看你代码里的几个小问题:

  1. 事件监听里用到的bookStorage定义在循环末尾,这会导致事件触发时变量还没定义(或者拿到的是最后一次循环的对象,因为作用域问题);
  2. 循环里的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é

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 19:48:12