用JavaScript获取最接近的更大ID 优化商品退回原列表的实现方案
性能优化解决方案
原有代码的核心问题
- 遍历逻辑没有提前终止:找到符合条件的插入位置后,没有中断
each循环,会继续跑完所有待选商品节点,几百个商品时会做大量无用判断 - 多余DOM操作:先克隆节点再删除原节点,完全可以直接移动节点减少DOM开销
- 存在逻辑BUG:按钮用了重复id,多个已选商品时事件触发异常;纯数字id直接字符串比较会出现
"10" < "2"的排序错误 - 重复DOM查询:每次点击都重新查询所有待选商品节点
快速优化版本(改3行代码性能提升数倍)
不需要改整体逻辑,只要补全循环终止、优化节点移动、修复id比较问题,几百个商品场景完全够用:
// 先把按钮的id改成class,避免重复id,事件绑定改成绑定class $(document).on('click', ".remove_product", function () { var product = $(this).closest("li"), // 提前转成数字id,避免字符串比较错误 productId = Number(product.attr('id')), found = false; // 提前缓存待选列表节点 const $productItems = $('.products_list li'); $productItems.each(function() { if(Number(this.id) > productId && !found ){ // 直接移动节点,不用克隆 product.insertBefore(this); found = true; // 加这行终止循环,不用继续遍历后面的节点 return false; } }); if(!found) product.appendTo(".products_list"); // 不用再remove,insertBefore/appendTo已经把节点移走了 })
对应HTML修改按钮部分:
<button class="remove_product">remove product</button>
更高性能版本(千级以上商品适用)
如果后续商品数量会涨到上千个,可以维护一个有序的待选商品id数组,用二分查找定位插入位置,时间复杂度从O(n)降到O(logn):
// 页面初始化时生成有序的待选id数组,后续增删商品时同步更新这个数组即可 let sortedProductIds = $('.products_list li').map(function(){ return Number(this.id) }).get(); const $productList = $('.products_list'); $(document).on('click', ".remove_product", function () { const $product = $(this).closest("li"); const productId = Number($product.attr('id')); // 二分查找第一个比当前id大的位置 let left = 0, right = sortedProductIds.length; while(left < right) { const mid = Math.floor((left + right)/2); if(sortedProductIds[mid] > productId) { right = mid; } else { left = mid + 1; } } // 插入到对应位置 if(left === sortedProductIds.length) { $product.appendTo($productList); sortedProductIds.push(productId); } else { $product.insertBefore($productList.children().eq(left)); sortedProductIds.splice(left, 0, productId); } })
内容的提问来源于stack exchange,提问作者saida lachgar
相关产品推荐
相关产品推荐

