JS价格排序异常:按数字首位排序而非数值大小,求修复
解决商品价格排序时按字符串首位比较的问题
你的排序逻辑出现错误的核心原因是:getAttribute('data-price') 返回的是字符串类型,而非数值类型。当JavaScript比较字符串大小时,会按字符的ASCII码逐位对比,比如 "230" 和 "25" 对比时,第二位 "3" 的ASCII码小于 "5",因此会判定 "230" < "25",最终出现你看到的错误排序结果。
以下是具体修复方案:
1. 修复排序时的数值类型转换
在SortElem函数的排序回调中,必须将取到的价格字符串转为数值类型后再比较:
sortli = li.sort((a, b)=>{ // 转成数值类型再执行比较逻辑 const ax = Number(a.getAttribute('data-price')); const bx = Number(b.getAttribute('data-price')); // 直接返回差值,逻辑更简洁直观 return asc ? ax - bx : bx - ax; });
2. 确保初始化函数被调用
你的代码中定义了SortProduct但未执行,导致ar数组为空,默认排序逻辑会失效。需要在DOM加载完成后调用该函数完成初始化:
// 页面加载完成后执行初始化 document.addEventListener('DOMContentLoaded', () => { SortProduct(); });
3. 修正语法错误
代码末尾存在一个多余的},需要删除(SortElem函数结束后的额外闭合括号)。
完整修复后的代码
let field = document.querySelector('.items'); let li = Array.from(field.children); let ar = []; // 将ar提升到全局作用域,避免初始化后无法访问 function SortProduct() { const select = document.getElementById('sortby'); for(const item of li){ const priceEl = item.querySelector(".pop-price"); const priceText = priceEl.textContent.trim(); const priceValue = Number(priceText.substring(1)); item.setAttribute("data-price", priceValue); ar.push(item); } } // 初始化商品数据 document.addEventListener('DOMContentLoaded', SortProduct); // 绑定排序选择器的change事件 document.getElementById('sortby').onchange = sortingValue; function sortingValue(){ if (this.value === 'Default') { while (field.firstChild) { field.removeChild(field.firstChild); } field.append(...ar); } else if (this.value === 'lowtohigh') { SortElem(field, li, true) } else if (this.value === 'hightolow') { SortElem(field, li, false) } } function SortElem(field, itemList, isAsc){ const sortedList = itemList.sort((a, b)=>{ const priceA = Number(a.getAttribute('data-price')); const priceB = Number(b.getAttribute('data-price')); // 升序返回价格差,降序返回反向差值 return isAsc ? priceA - priceB : priceB - priceA; }); // 清空原有元素并添加排序后的列表 while (field.firstChild) { field.removeChild(field.firstChild); } field.append(...sortedList); } // 注释无效调用:SortElem需要传入参数才能执行 // console.log(SortElem())
额外优化建议
- 可以用
element.dataset.price代替getAttribute,语法更简洁:const priceA = Number(a.dataset.price); - 可以将价格值直接存储在元素的自定义属性中(如
item._price = priceValue),避免每次排序都从DOM读取,提升性能
内容的提问来源于stack exchange,提问作者QuantiDiuS
相关产品推荐
相关产品推荐

