Magento 2:JavaScript中如何获取购物车商品数量变更的旧值?
问题:修改购物车商品数量时无法获取修改前的数量值
我有一个页面加载时运行的JavaScript文件,定义了两个变量分别存储购物车商品列表和商品总数。脚本里的subscribe方法会在购物车更新时触发,添加、移除商品时逻辑正常,但修改商品数量时,始终拿不到修改前的数量值。
相关代码
var cart = customerData.get('cart'); // 定义变量用于在subscribe内对比 var count = cart().summary_count; var currentItems = [...cart().items]; // 监听购物车变化 cart.subscribe(function () { // 如果总数有变化 if (cart().summary_count !== count) { for(let i = 0; i < cart().summary_count; i++){ var foundItem = currentItems.find(x => x.product_id == cart().items[i].product_id); var currentItem = cart().items[i]; // 这里两个值总是相同 if(foundItem.qty < currentItem.qty){ var qtyChange = currentItem.qty - foundItem.qty; } } } // 更新总数为新值 count = cart().summary_count; // 更新商品数组为新值 currentItems = cart().items; });
补充说明
cart().summary_count会正常更新,但外部定义的currentItems数组里的qty值会和cart().items里的qty同步变化。另外注意到currentItems中的qty是字符串类型,而cart().items中的qty是数字类型。
截图说明:修改item_id为269的商品数量后,开发者工具中显示两个数组的
qty值同步发生了变化。
请问我哪里处理错了?
解决方案
问题根源
- 浅拷贝导致引用共享:你用
[...cart().items]复制数组属于浅拷贝,数组里的商品对象还是和原cart().items里的对象共用同一个引用。当购物车商品数量更新时,原对象的qty属性被修改,currentItems里的对应值也会跟着变,自然拿不到修改前的旧值。 - 类型不统一:
qty的字符串/数字类型差异,可能导致比较逻辑出现隐性错误。
修正后的代码
var cart = customerData.get('cart'); // 深拷贝初始购物车数据,保存独立快照 var count = cart().summary_count; var currentItems = JSON.parse(JSON.stringify(cart().items)); // 监听购物车变化 cart.subscribe(function () { const newCart = cart(); const newCount = newCart.summary_count; const newItems = newCart.items; // 遍历新商品列表,对比旧数据找差异 newItems.forEach(newItem => { // 统一转成数字类型,避免类型问题 const newQty = Number(newItem.qty); const oldItem = currentItems.find(item => item.product_id === newItem.product_id); if (oldItem) { const oldQty = Number(oldItem.qty); if (newQty !== oldQty) { const qtyChange = newQty - oldQty; console.log(`商品${newItem.product_id}数量变化:${qtyChange}`); // 这里写你需要的数量变化处理逻辑 } } else { // 处理新添加的商品 console.log(`新增商品${newItem.product_id},数量${newQty}`); } }); // 处理被移除的商品 currentItems.forEach(oldItem => { const exists = newItems.find(item => item.product_id === oldItem.product_id); if (!exists) { console.log(`移除商品${oldItem.product_id}`); } }); // 更新快照为最新购物车数据 count = newCount; currentItems = JSON.parse(JSON.stringify(newItems)); });
关键优化点
- 深拷贝快照:用
JSON.parse(JSON.stringify())实现深拷贝,让currentItems里的商品对象完全独立于原购物车数据,修改后不会互相影响。如果你的商品对象包含函数、日期等特殊类型,建议用递归深拷贝或者Lodash的_.cloneDeep方法。 - 统一类型:用
Number()把qty转成数字,避免字符串和数字比较时的隐性错误。 - 全面覆盖场景:不仅处理数量变化,还覆盖了商品添加、移除的情况,同时不再依赖
summary_count的变化判断,即使总数不变(比如添加一个商品同时移除另一个)也能捕获变化。
内容的提问来源于stack exchange,提问作者JamesS
相关产品推荐
相关产品推荐

