无框架JavaScript实现HTML元素排序问题求助
问题:点击NAME按钮无法实现页面元素按字母排序
我找不到清晰的方案来排序页面上显示的HTML元素。期望点击NAME按钮后,页面中的元素能按字母顺序排序。作为编程新手,我不知道如何搜索相关解决方案。我尝试使用sort函数,它在控制台打印列表时有效,但页面上没有任何变化。
原JavaScript代码
let closebtns = document.querySelectorAll("span"); //add animal button form const addMovieModal = document.getElementById('add-modal'); const startAddMovieButton = document.querySelector('section button'); const backdrop = document.getElementById('backdrop'); const cancelAdd = addMovieModal.querySelector('.btn--passive'); const addButton = addMovieModal.querySelector('#btn--success'); const userInput = addMovieModal.querySelectorAll('input'); const clearInputs = () => { for (const usrInput of userInput) { usrInput.value = ""; } } let listOfAnimals = [{ name: "Meowsalot", age: 10, type: "cat", favFoods: ["tuna", "catnip", "celery"] }, { name: "Barksalot", age: 7, type: "cat", favFoods: [] }, { name: "Barksalot", age: 10, type: "dog", favFoods: ["tuna", "catnip", "celery"] } ]; const name = "NAME: "; const age = "AGE: "; const typ = "TYPE: "; const favFood = "FOOD: " document.getElementById('li').innerHTML = name + listOfAnimals[0].name + "</br>" + age + listOfAnimals[0].age + "</br>" + typ + listOfAnimals[0].type + "</br>" + favFood + listOfAnimals[0].favFoods + "</br>"; document.getElementById('li1').innerHTML = name + listOfAnimals[1].name + "</br>" + age + listOfAnimals[1].age + "</br>" + typ + listOfAnimals[1].type + "</br>" + favFood + listOfAnimals[1].favFoods + "</br>" document.getElementById('li2').innerHTML = name + listOfAnimals[2].name + "</br>" + age + listOfAnimals[2].age + "</br>" + typ + listOfAnimals[2].type + "</br>" + favFood + listOfAnimals[2].favFoods + "</br>" const addNewAnimal = () => { const nameAnimal = userInput[0].value; const type = userInput[2].value; const ageAnimal = userInput[3].value; const image = userInput[1].value; if (nameAnimal.trim() === "" || type.trim() === "" || image.trim() === "" || ageAnimal.trim() === "" ) { alert("Please enter a valid value "); return; } const newAnimal = { name: nameAnimal, url: image, type: type, age: ageAnimal, }; listOfAnimals.push(newAnimal); console.log(newAnimal); toggleMovieModal(); renderLiElement(newAnimal.name, newAnimal.type, newAnimal.age, newAnimal.url); clearInputs(); }; addButton.addEventListener('click', addNewAnimal); const renderLiElement = (type, name, age, imageURL) => { const newLiElement = document.createElement('li'); newLiElement.innerHTML = `<li class="animalElement"> <img alt="${imageURL}" src="${imageURL}"> <span class="close">&times;</span> <ul class="ulOfLi"> <li>Name : ${name}</li> <li>Age : ${age}</li> <li>Type : ${type}</li> <li>Food </li> </ul> </li>`; newLiElement.querySelector('.close').addEventListener('click', closeFunction); const listRoot = document.getElementById('ulList'); listRoot.append(newLiElement); newLiElement.style.border = 'none'; } const toggleBackdrop = () => { backdrop.classList.toggle('visible'); }; const toggleMovieModal = () => { addMovieModal.classList.toggle('visible'); toggleBackdrop(); }; const cancel = () => { toggleMovieModal(); clearInputs(); }; startAddMovieButton.addEventListener('click', toggleMovieModal); backdrop.addEventListener('click', toggleMovieModal); cancelAdd.addEventListener('click', cancel); //close li element const closeFunction = function() { this.parentElement.style.display = 'none'; }; for (i = 0; i < closebtns.length; i++) { closebtns[i].addEventListener("click", closeFunction); }
原HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="Zadanie1.css" rel="stylesheet" type="text/css"> <script src="Zadanie1.js" defer></script> </head> <body> <div class="body"> <div class="titles"> <h4>Sort</h4> <h4>Filter</h4> </div> <div class="controlPanel" id="controlPanel"> <button id="sort-age">AGE</button> <button class="sort-name" id="sort-name">NAME</button> <input type="number" placeholder="Types" id="input-number" /> <label for="input-number"></label> </div> <ul class="UL" id="ulList"> <li class="animalElement"> <img alt="cat-2" src="dog-1.jpg"> <span class="close">×</span> <ul class="ulOfLi" id="li2"> </ul> </li> <li class="animalElement"> <img alt="cat-1" src="cat-2.jpg"> <span class="close">×</span> <ul class="ulOfLi" id="li1"> </ul> </li> <li class="animalElement"> <img alt="dog-1" src="cat-1.jpg"> <span class="close">×</span> <p class="ulOfLi" id="li"> </p> </li> </ul> <div id="backdrop"></div> <div class="modal card" id="add-modal"> <div class="modal__content"> <label for="name"></label> <input type="text" name='name' id="name" placeholder="NAME" /> <label for="imageURL"></label> <input type="text" name="imageURL" id="imageURL" placeholder="url" /> <label for="type"></label> <input type="text" name="type" id="type" placeholder="TYPE" /> <label for="age"></label> <input placeholder="AGE" type="number" step="1" max="20" min="1" name="age" id="age" /> </div> <div class="modal__actions"> <button class="btn btn--passive">Cancel</button> <button class="btn btn--success" id="btn--success">Add</button> </div> </div> <section> <button class="add">×</button> </section> </div> </body> </html>
问题分析
你只对listOfAnimals数组执行了排序,但没有将排序后的结果同步到页面DOM中。页面初始元素是通过硬编码设置innerHTML生成的,新增元素用renderLiElement添加,但排序后没有重新渲染整个列表,所以页面没有变化。另外renderLiElement的参数顺序和调用时不一致,会导致渲染内容错误。
解决方案
- 给NAME按钮添加点击事件,触发排序和重新渲染逻辑
- 实现数组排序函数,按name字段进行不区分大小写的字母排序
- 清空现有列表元素,根据排序后的数组重新渲染所有动物项
- 统一初始元素和新增元素的渲染方式,避免硬编码
- 修复
renderLiElement的参数顺序问题
修改后的完整代码
JavaScript代码
let closebtns = document.querySelectorAll("span"); //add animal button form const addMovieModal = document.getElementById('add-modal'); const startAddMovieButton = document.querySelector('section button'); const backdrop = document.getElementById('backdrop'); const cancelAdd = addMovieModal.querySelector('.btn--passive'); const addButton = addMovieModal.querySelector('#btn--success'); const userInput = addMovieModal.querySelectorAll('input'); const sortNameBtn = document.getElementById('sort-name'); const clearInputs = () => { for (const usrInput of userInput) { usrInput.value = ""; } } let listOfAnimals = [{ name: "Meowsalot", age: 10, type: "cat", favFoods: ["tuna", "catnip", "celery"], url: "cat-1.jpg" }, { name: "Barksalot", age: 7, type: "cat", favFoods: [], url: "cat-2.jpg" }, { name: "Barksalot", age: 10, type: "dog", favFoods: ["tuna", "catnip", "celery"], url: "dog-1.jpg" } ]; // 统一渲染所有动物元素的函数 const renderAllAnimals = () => { const listRoot = document.getElementById('ulList'); // 清空现有内容 listRoot.innerHTML = ''; // 遍历数组渲染每个元素 listOfAnimals.forEach(animal => { renderLiElement(animal.name, animal.type, animal.age, animal.url, animal.favFoods); }); // 重新绑定关闭按钮事件 closebtns = document.querySelectorAll("span"); for (let i = 0; i < closebtns.length; i++) { closebtns[i].addEventListener("click", closeFunction); } }; const addNewAnimal = () => { const nameAnimal = userInput[0].value; const type = userInput[2].value; const ageAnimal = userInput[3].value; const image = userInput[1].value; if (nameAnimal.trim() === "" || type.trim() === "" || image.trim() === "" || ageAnimal.trim() === "" ) { alert("Please enter a valid value "); return; } const newAnimal = { name: nameAnimal, url: image, type: type, age: ageAnimal, favFoods: [] }; listOfAnimals.push(newAnimal); console.log(newAnimal); toggleMovieModal(); clearInputs(); }; // 修复参数顺序:name, type, age, imageURL, favFoods 对应函数参数 const renderLiElement = (name, type, age, imageURL, favFoods) => { const newLiElement = document.createElement('li'); newLiElement.className = 'animalElement'; newLiElement.innerHTML = ` <img alt="${imageURL}" src="${imageURL}"> <span class="close">×</span> <ul class="ulOfLi"> <li>Name : ${name}</li> <li>Age : ${age}</li> <li>Type : ${type}</li> <li>Food : ${favFoods.length > 0 ? favFoods.join(', ') : 'None'}</li> </ul>`; newLiElement.querySelector('.close').addEventListener('click', closeFunction); const listRoot = document.getElementById('ulList'); listRoot.append(newLiElement); } // 按名称排序的函数 const sortAnimalsByName = () => { // 不区分大小写排序 listOfAnimals.sort((a, b) => { const nameA = a.name.toLowerCase(); const nameB = b.name.toLowerCase(); if (nameA < nameB) return -1; if (nameA > nameB) return 1; return 0; }); // 重新渲染页面 renderAllAnimals(); }; const toggleBackdrop = () => { backdrop.classList.toggle('visible'); }; const toggleMovieModal = () => { addMovieModal.classList.toggle('visible'); toggleBackdrop(); }; const cancel = () => { toggleMovieModal(); clearInputs(); }; // 绑定事件 startAddMovieButton.addEventListener('click', toggleMovieModal); backdrop.addEventListener('click', toggleMovieModal); cancelAdd.addEventListener('click', cancel); addButton.addEventListener('click', addNewAnimal); sortNameBtn.addEventListener('click', sortAnimalsByName); //close li element const closeFunction = function() { this.parentElement.style.display = 'none'; }; // 页面加载完成后初始渲染 renderAllAnimals();
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Animal List</title> <link href="Zadanie1.css" rel="stylesheet" type="text/css"> <script src="Zadanie1.js" defer></script> </head> <body> <div class="body"> <div class="titles"> <h4>Sort</h4> <h4>Filter</h4> </div> <div class="controlPanel" id="controlPanel"> <button id="sort-age">AGE</button> <button class="sort-name" id="sort-name">NAME</button> <input type="number" placeholder="Types" id="input-number" /> <label for="input-number"></label> </div> <ul class="UL" id="ulList"> <!-- 元素将通过JS动态渲染 --> </ul> <div id="backdrop"></div> <div class="modal card" id="add-modal"> <div class="modal__content"> <label for="name"></label> <input type="text" name='name' id="name" placeholder="NAME" /> <label for="imageURL"></label> <input type="text" name="imageURL" id="imageURL" placeholder="url" /> <label for="type"></label> <input type="text" name="type" id="type" placeholder="TYPE" /> <label for="age"></label> <input placeholder="AGE" type="number" step="1" max="20" min="1" name="age" id="age" /> </div> <div class="modal__actions"> <button class="btn btn--passive">Cancel</button> <button class="btn btn--success" id="btn--success">Add</button> </div> </div> <section> <button class="add">Add Animal</button> </section> </div> </body> </html>
内容的提问来源于stack exchange,提问作者Patryk Jutrowski
相关产品推荐
相关产品推荐

