页面刷新时保留prod__viewed类状态的技术问询
解决页面刷新后记住已查看商品元素的问题
你当前的核心问题是对sessionStorage的使用逻辑有误——你尝试直接存储jQuery对象,这显然无法正确保存元素状态。下面我会帮你修正代码,实现刷新页面后记住哪些.prod__item已经添加了.prod__viewed类的需求。
问题分析
你的原sessionStorage代码存在几个关键错误:
- 选择器错误:
$("prod__item")缺少类选择器的点号,应该是$(".prod__item") - 存储内容错误:你把jQuery对象直接存入sessionStorage,而sessionStorage只能存储字符串类型的数据
- 读取逻辑错误:读取时直接把存储内容当作类名添加,完全不符合需求逻辑
修正后的完整代码
JavaScript部分
// 页面加载时恢复已查看的商品状态 $(window).on('load', function() { // 从sessionStorage读取已查看的商品ID数组,没有则为空数组 const viewedItems = JSON.parse(sessionStorage.getItem('prodViewed')) || []; viewedItems.forEach(itemId => { $(`.prod__item[data-id="${itemId}"]`).addClass('prod__viewed'); }); // 初始化计数和进度条 updateProdCountAndProgress(); }); $(window).on('resize scroll', function() { $('.prod__item').each(function() { const $item = $(this); const itemId = $item.data('id'); // 如果元素已在视口且未标记为已查看 if ($item.prodInViewport() && !$item.hasClass('prod__viewed')) { $item.addClass('prod__viewed'); // 更新sessionStorage中的已查看列表 const viewedItems = JSON.parse(sessionStorage.getItem('prodViewed')) || []; if (!viewedItems.includes(itemId)) { viewedItems.push(itemId); sessionStorage.setItem('prodViewed', JSON.stringify(viewedItems)); } } }); updateProdCountAndProgress(); }); // 封装计数和进度条更新逻辑 function updateProdCountAndProgress() { const numItems = $('.prod__item').length; const totalNumItems = $('.prod__viewed').length; const prodCountCheck = $('.prod__count__container'); const positionY = $(window).scrollTop(); const pageHeight = $(window).height(); const scrollHeight = $('.prod__wrapper').height(); const scrollPercent = scrollHeight > pageHeight ? (positionY / (scrollHeight - pageHeight)) * 100 : 0; const prodCountElement = $('.prod__count__container').outerHeight(); if (prodCountCheck.length === 1) { $('.prod__count__content') .html('<span>You\'ve seen <strong>' + totalNumItems + '</strong> of <strong>' + numItems + '</strong> prods</span>'); $('.prod__load__bar').css({ 'top': prodCountElement, 'width': scrollPercent + "%" }); } } $.fn.prodInViewport = function() { const elementTop = $(this).offset().top; const elementBottom = elementTop + $(this).outerHeight(); const viewportTop = $(window).scrollTop(); const viewportBottom = viewportTop + $(window).height(); return elementBottom > viewportTop && elementTop < viewportBottom; };
HTML部分(需要给每个商品添加唯一标识)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <section class="prod__wrapper"> <div class="prod__container"> <div class="prod__item" data-id="item-1"> <div class="prod__item--img"> <img src="https://images-na.ssl-images-amazon.com/images/I/81Lz-p7eRDL._SL1500_.jpg"> </div> <div class="prod__item--deets"> <div class="prod__name"> My Hero Academia Two Heroes Blu Ray </div> <div class="prod__price"> £14.99 </div> </div> </div> <div class="prod__item" data-id="item-2"> <div class="prod__item--img"> <img src="https://images-na.ssl-images-amazon.com/images/I/81Lz-p7eRDL._SL1500_.jpg"> </div> <div class="prod__item--deets"> <div class="prod__name"> My Hero Academia Two Heroes Blu Ray </div> <div class="prod__price"> £14.99 </div> </div> </div> <div class="prod__item" data-id="item-3"> <div class="prod__item--img"> <img src="https://images-na.ssl-images-amazon.com/images/I/81Lz-p7eRDL._SL1500_.jpg"> </div> <div class="prod__item--deets"> <div class="prod__name"> My Hero Academia Two Heroes Blu Ray </div> <div class="prod__price"> £14.99 </div> </div> </div> </div> </section>
CSS部分保持你原来的代码不变即可。
关键逻辑说明
- 唯一标识:给每个
.prod__item添加data-id属性,作为元素的唯一识别符,确保刷新后能准确找到对应的元素。 - sessionStorage存储:用JSON数组存储已查看商品的ID,因为sessionStorage只能存字符串,所以用
JSON.stringify和JSON.parse进行格式转换。 - 页面加载恢复状态:页面加载时读取sessionStorage中的数组,遍历给对应ID的元素添加
.prod__viewed类。 - 视口检测更新:当元素进入视口且未被标记时,添加类并更新sessionStorage中的数组。
- 逻辑封装:把计数和进度条更新逻辑封装成函数,避免重复代码,提高可维护性。
这样修改后,页面刷新后就能正确记住哪些商品已经被标记为已查看了。
内容的提问来源于stack exchange,提问作者Nick Else
相关产品推荐
相关产品推荐

