You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无框架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">×</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">&times;</span>
        <ul class="ulOfLi" id="li2">
        </ul>
      </li>
      <li class="animalElement">
        <img alt="cat-1" src="cat-2.jpg">
        <span class="close">&times;</span>
        <ul class="ulOfLi" id="li1">
        </ul>
      </li>
      <li class="animalElement">
        <img alt="dog-1" src="cat-1.jpg">
        <span class="close">&times;</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">&times;</button>
    </section>
  </div>
</body>

</html>

问题分析

你只对listOfAnimals数组执行了排序,但没有将排序后的结果同步到页面DOM中。页面初始元素是通过硬编码设置innerHTML生成的,新增元素用renderLiElement添加,但排序后没有重新渲染整个列表,所以页面没有变化。另外renderLiElement的参数顺序和调用时不一致,会导致渲染内容错误。

解决方案

  1. 给NAME按钮添加点击事件,触发排序和重新渲染逻辑
  2. 实现数组排序函数,按name字段进行不区分大小写的字母排序
  3. 清空现有列表元素,根据排序后的数组重新渲染所有动物项
  4. 统一初始元素和新增元素的渲染方式,避免硬编码
  5. 修复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">&times;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:25:44