JS实现HTML商品排序时for循环死循环及上层DOM元素引用问题
如何获取向上两层的父元素
方案1:连续调用两次parentElement
从.product-name元素出发,连续访问两次父元素即可拿到外层的.product节点,示例写法:
const productName = document.querySelector('.product-name'); // .product-name的父元素是.product-data,再上层父元素就是.product const productItem = productName.parentElement.parentElement;
方案2(更推荐):使用closest()直接匹配目标祖先
不需要手动数层级,直接匹配最近的符合选择器的祖先元素,即使后续HTML结构有微调也不会失效:
const productName = document.querySelector('.product-name'); const productItem = productName.closest('.product');
原有代码无限循环的问题修复
你原来的代码死循环的核心原因是:只交换了实际DOM节点的顺序,但存储节点的productArr数组顺序一直没有更新,每次冒泡判断都是基于初始的数组顺序,永远会命中交换条件,导致循环无法退出。
另外你实现的冒泡排序逻辑也不完整,单次遍历找到第一个需要交换的元素就break,排序效率低且逻辑容易出错,更简单的实现方式是直接用数组的sort()方法排序后重新插入DOM,代码更简洁也不容易出问题。
修正后的完整代码
var sortingSel = document.querySelector(".order"); var productContainer = document.querySelector(".products"); var product = document.querySelectorAll("div.product"); var productArr = Array.from(product); sortingSel.onchange = function(){ var sortingOpt = parseInt(sortingSel.options[sortingSel.selectedIndex].value); switch(sortingOpt){ case 2: // 按商品名称字母升序排序 productArr.sort(function(a, b){ var nameA = a.querySelector(".product-name").innerText.toLowerCase(); var nameB = b.querySelector(".product-name").innerText.toLowerCase(); return nameA.localeCompare(nameB); }); // 把排序后的节点重新插入容器,已存在的DOM节点会自动从原位置移除 productArr.forEach(function(item){ productContainer.appendChild(item); }); break; default: console.log("def"); } }
内容的提问来源于stack exchange,提问作者Katalin
相关产品推荐
相关产品推荐

