简体   繁体   English

无法从数组中删除元素

[英]Trouble removing an element from an array

I started self teaching myself JavaScript a couple of weeks ago and have run into a problem I am unable to solve. 几周前,我开始自学JavaScript,但遇到了无法解决的问题。 The program works by allowing a user to enter a list of names which is saved in an array and also shown on the screen as li elements. 该程序通过允许用户输入名称列表进行工作,该名称列表保存在数组中,并在屏幕上显示为li元素。 The program will then randomly select one of the people entered. 然后,程序将随机选择输入的人员之一。 My problem occurs when trying to remove a person from the list. 尝试从列表中删除一个人时发生我的问题。 I am able to remove them from the HTML but not from the array. 我可以将它们从HTML中删除,但不能从数组中删除。 I have attempted to use the .splice method as shown below but this only removes the last element in the array. 我试图使用如下所示的.splice方法,但这只会删除数组中的最后一个元素。 I believe this to be due to indexOf(li.value) not being suitable for this use but do not know what else to try. 我相信这是由于indexOf(li.value)不适合此用途,但不知道还要尝试什么。 Any help is much appreciated. 任何帮助深表感谢。

<!DOCTYPE html>
<html>
  <head>
    <title>Student Randomiser</title>
    <link rel="stylesheet" href="custom.css">
  </head>
  <body>
    <h1 id="myHeading">Student Randomiser</h1>
    <div class="list">
      <p class="description">Add Students:</p>
      <input type="text" class="studentName" value="Write Students Here">
      <button class="addStudent">Add student</button>
      <ul id= "listStudentNames">
      </ul>
      <button class="randomStudent">Select a random student</button>
</div>
<script src="randomNamePicker.js"></script>
</body>
</html>




const addStudent = document.querySelector('button.addStudent');
const studentName = document.querySelector('input.studentName');
const randomStudent = document.querySelector('button.randomStudent');
const listStudentNames = document.querySelector("ul");
let students = [
]
let number
window.onload=function(){
addStudent.addEventListener('click', addStudentToList);
randomStudent.addEventListener('click', selectRandomStudent);
listStudentNames.addEventListener("click", removeStudent);
}
function addButtons(li){
  let remove =document.createElement('button');
  remove.className= "removeStudent";
  remove.textContent = "Remove Student";
  li.appendChild(remove)
}

function removeStudent (){
  if (event.target.tagName === "BUTTON") {
let li = event.target.parentNode;
let ul = li.parentNode;
let i = students.indexOf(li.value);
students.splice(i,1);
ul.removeChild(li);
  }}

function getRandomIntInclusive(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  number =  Math.floor(Math.random() * (max - min)) + min;
}

function addStudentToList() {
  students.push(studentName.value);
  var ul = document.getElementById("listStudentNames");
  var li = document.createElement("li");
  li.appendChild(document.createTextNode(studentName.value));
  addButtons(li);
  ul.appendChild(li);
  studentName.value = "";
}

function selectRandomStudent(){
getRandomIntInclusive(0, students.length);
alert(students[number]);
}

There are a variety of issues with your code, some are programmatic, some are stylistic and some are your logic. 您的代码有很多问题,有些是编程的,有些是风格的,有些是您的逻辑。

Your main issue is that the only elements that have a value property are form elements. 您的主要问题是,具有value属性的唯一元素是表单元素。 So, when you write: 因此,当您编写:

let i = students.indexOf(li.value);

You have an issue because you set li up to be the parent node of event.target . 您遇到了一个问题,因为您将li设置为event.target的父节点。 event.target is the element that initiated the event, in this case a <button> and the parent of the button is <div> , which (again) doesn't have a value property and is not the correct element anyway. event.target是启动事件的元素,在这种情况下,是<button><button>的父元素是<div> ,(再次)它没有value属性,而且也不是正确的元素。

This value is what you are basing your splice on. 此值是您splice基础。 Instead, you need to get the index position of the li within the list of li elements or the array (they should be the same). 相反,你需要得到的索引位置li的名单内li的元素或阵列(他们应该是相同的)。

Next, you don't really have a need for an array in this scenario in the first place since all of the student names will be elements within a <ul> element, this means that they can be accessed via a "node list", which is an "array-like" object that supports a length property, is enumerable and indexable. 接下来,在这种情况下,您实际上并不需要数组,因为所有学生姓名都是<ul>元素中的元素,这意味着可以通过“节点列表”来访问它们,它是一个支持length属性的“类似数组”的对象,是可枚举和可索引的。 Keeping the <li> element content in a synchronized array doesn't add any value here and makes the overall task more complex that it need be because you are forced to keep the HTML list in sync with the array. <li>元素内容保留在同步数组中不会在此处添加任何值,并且会使整体任务变得更加复杂,因为您被迫使HTML列表与数组保持同步。

Having said all of this, here's a working example of what you are attempting, with comments inline to explain why my code differs from yours. 综上所述,这是您正在尝试的一个有效示例,并带有内联注释以解释为什么我的代码与您的代码不同。

 // When the DOM is loaded and all elements are accessible... window.addEventListener("DOMContentLoaded", function(){ // Get references to the DOM elements needed to solve problem // Using "var" here is perfectly acceptable as their scope will // be the entire parent function, which is what we want. Get all // these references just once so we don't have to keep scanning // the DOM for them each time we want to work with the list. Also, // name your variables "noun"-like names when they refer to elements var btnAdd = document.querySelector(".addStudent"); var btnRandom = document.querySelector(".randomStudent"); var list = document.getElementById("listStudentNames"); var student = document.querySelector("input[type='text']"); var output = document.querySelector(".report"); // Set up an empty array to keep the synchronized student list in var students = []; // Set up click event handling functions btnAdd.addEventListener("click", addStudent); btnRandom.addEventListener("click", getRandomStudent); function addStudent(){ // Make sure there was valid input if(student.value.trim() === ""){ return; } // Create a new <li> element var li = document.createElement("li"); // Set new element up with a click event handler that will // cause the current element to be removed from the list li.addEventListener("click", removeStudent); // Populate the element with the text from the <input> // The element gets raw text set with the .textContent property // while content of form elements is gotten with the "value" // property li.textContent = student.value; // Update the list id's to match the array indexes sync(); // Add the element to the end of the <ul>'s list elements list.appendChild(li); // Add new student to the array: students.push(student.value); // Clear value from input student.value = ""; logResults(); } function getRandomStudent(){ console.clear(); if(students.length){ // Use the built-in JavaScript Math object to get a random number // between 0 (inclusive) and 1 (exclusive) then multiply that // number by the lenght of the <li> node list to get a random // number between 0 and the amount of elements in the array var random = Math.floor(Math.random() * list.children.length); console.log("Random student is: " + list.children[random].textContent); } else { console.log("No students to choose from!"); } } function removeStudent (evt){ // Re-sync the indexes of the HTML elements to match the array sync(); // Remove corresponding student from array first... console.clear(); console.log("Student " + evt.target.id + " about to be removed"); students.splice(+evt.target.id, 1); // Every event handling function automatically gets a reference // to the event that triggered the function sent into it. We can // access that event to get a reference to the actual DOM object // the caused the event to be triggered with "event.target" list.removeChild(evt.target); logResults(); } // We have to keep the HTML element indexes in sync with the array indexes function sync(){ // Loop through the HTML elements and give them an id that corresponds // to the index position of its counterpart in the array. Array.prototype.forEach.call(list.children, function(el, index){ el.id = index; }); } // This is just a function for updating the display to show the contents // of the array to confirm that it is in sync with the list function logResults(){ output.innerHTML = "Array now contains: <br>" + students.join("<br>"); } }); 
 .list, .report { float:left; } .report { background-color:aliceblue; } 
 <div class="list"> <input type="text" class="studentName" placeholder="Enter Student Name Here"> <button class="addStudent">Add student to list</button> <ul id= "listStudentNames"> </ul> <p class="description">(Click on a student to remove them from the list.)</p> <button class="randomStudent">Select a random student</button> </div> <div class="report"></div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM