简体   繁体   English

使用纯JavaScript删除待办事项列表中的列表项

[英]Removing list item in to-do list using pure JavaScript

Let me start by saying that: 让我首先说:

  1. I've already looked at a lot of documentation about resolving this problem 我已经看过很多有关解决此问题的文档
  2. I'm still very new to JavaScript. 我对JavaScript还是很陌生。

The problem: the remove button doesn't remove the corresponding content, which is a li item. 问题:删除按钮不会删除对应的内容,这是一个li项目。 To me, that means the problem is in step 7 removeToDo.addEventListener or in step 8 function removeToDoItem , but I could be wrong. 对我而言,这意味着问题出在步骤7的removeToDo.addEventListener或步骤8的function removeToDoItem ,但我可能是错的。

 //2) SECOND STEP: build the function that will control everything function onReady() { //2.1) creates and houses the current state of to-do list var toDos = []; //3) THIRD STEP: Event Listener - this accesses the HTML form element var addToDoForm = document.getElementById('addToDoForm'); //2.2) build function that creates/adds list items function createNewToDo() { //2.3) accesses the text input from the form var newToDoText = document.getElementById('newToDoText'); //2.4) adds new item to the toDos array toDos.push({ title: newToDoText.value, complete: false }); //2.5) clears the text in the form input field so user doesn't need to newToDoText.value=''; renderTheUI(toDos); } //8) EIGHT STEP: build function that deletes list item function removeToDoItem() { newLi.toDoList.removeChild(newLi); renderTheUI(toDos); } //5) FIFTH STEP: build the function that will render the UI function renderTheUI(toDos) { //5.1) Accesses the <ul> in the HTML var toDoList = document.getElementById('toDoList'); //5.9 sets each newLi to an empty string toDoList.innerHTML = ''; //5.2) Use forEach() array method to render each to-do as an <li> in the <ul> toDos.forEach(function(toDo) { //5.3 creates new <li> var newLi = document.createElement('li'); newLi.setAttribute('id', 'myLi'); //5.4 creates new checkbox var checkbox = document.createElement('input'); //6) SIXTH STEP: create remove button and set its attributes var removeToDo = document.createElement('input'); removeToDo.setAttribute('type', 'button'); removeToDo.setAttribute('value', 'remove'); removeToDo.setAttribute('id', 'removeButton'); //5.5 set var checkbox as a type checkbox checkbox.type = 'checkbox'; //5.6 assigns to-do item to newLi in the HTML newLi.innerHTML = toDo.title; //5.7 appends newLi to the to-do list toDoList.appendChild(newLi); //5.8 appends a checkbox to each newLi newLi.appendChild(checkbox); //6.1 append the remove button to each newLi newLi.appendChild(removeToDo); }); } //3.1) Event Listener - catches 'submit', prevents page reload, // and invokes the function createNewToDo addToDoForm.addEventListener('submit', function(event) { event.preventDefault(); createNewToDo(); }); //7) SEVENTH STEP: assign remove button event and invoke removeToDoItem() removeToDo.addEventListener('click', function(event) { removeToDoItem(); }); //4) FOURTH STEP: add the call that controls UI based on state renderTheUI(toDos); } //1) FIRST STEP: invokes the function onReady() when page loads window.onload = function() { onReady() }; 
 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>To-Do App</title> </head> <body> <h1>To-Do App</h1> <form id="addToDoForm"> <label for="newToDoText">New To-Do:</label> <input type="text" id="newToDoText"> <button type="submit">Add To-Do!</button> </form> <ul id="toDoList"> </ul> <script src="app.js"></script> </body> </html> 

You are binding click event listener to removeToDo whereas removeToDo is is present only inside renderUI function. 您将单击事件侦听器绑定到removeToDo,而removeToDo仅存在于renderUI函数中。 So your seventh step is wrong. 因此,您的第七步是错误的。 you need to add Event listener inside createUI itself. 您需要在createUI本身内部添加事件侦听器。 Replace your script with below code 用下面的代码替换您的脚本

//2) SECOND STEP: build the function that will control everything
function onReady() {

  //2.1) creates and houses the current state of to-do list
  var toDos = [];

  //3) THIRD STEP: Event Listener - this accesses the HTML form element
  var addToDoForm = document.getElementById('addToDoForm');

  //2.2) build function that creates/adds list items
  function createNewToDo() {

    //2.3) accesses the text input from the form
    var newToDoText = document.getElementById('newToDoText');

    //2.4) adds new item to the toDos array
    toDos.push({
      title: newToDoText.value,
      complete: false
    });

    //2.5) clears the text in the form input field so user doesn't need to
    newToDoText.value='';

    renderTheUI(toDos);
  }

  //8) EIGHT STEP: build function that deletes list item
  function removeToDoItem(index) {
    console.log(toDos);
    toDos.splice(index, 1);
    console.log(toDos);
    renderTheUI(toDos);
  }

  //5) FIFTH STEP: build the function that will render the UI
  function renderTheUI(toDos) {

    //5.1) Accesses the <ul> in the HTML
    var toDoList = document.getElementById('toDoList');

    //5.9 sets each newLi to an empty string
    toDoList.innerHTML = '';

    //5.2) Use forEach() array method to render each to-do as an <li> in the <ul>
    toDos.forEach(function(toDo, index) {
            //5.3 creates new <li>
      var newLi = document.createElement('li');
      newLi.setAttribute('id', 'myLi');

      //5.4 creates new checkbox
      var checkbox = document.createElement('input');

      //6) SIXTH STEP: create remove button and set its attributes
      var removeToDo = document.createElement('input');
      removeToDo.setAttribute('type', 'button');
      removeToDo.setAttribute('value', 'remove');
      removeToDo.setAttribute('id', 'removeButton');
      removeToDo.setAttribute('class', 'removeButton');
      removeToDo.setAttribute('data-index', index);

      //5.5 set var checkbox as a type checkbox
      checkbox.type = 'checkbox';

      //5.6 assigns to-do item to newLi in the HTML
      newLi.innerHTML = toDo.title;

      //5.7 appends newLi to the to-do list
      toDoList.appendChild(newLi);

      //5.8 appends a checkbox to each newLi
      newLi.appendChild(checkbox);

      //6.1 append the remove button to each newLi
      newLi.appendChild(removeToDo);

      removeToDo.addEventListener('click', function(event) {
        removeToDoItem(index);
      });
    });
  }

  //3.1) Event Listener - catches 'submit', prevents page reload,
  // and invokes the function createNewToDo
  addToDoForm.addEventListener('submit', function(event) {
    event.preventDefault();
    createNewToDo();
  });

  //4) FOURTH STEP: add the call that controls UI based on state
  renderTheUI(toDos);
}
onReady();

There are a few errors in your code, i have explained them below using comments. 您的代码中有一些错误,我在下面使用注释解释了它们。 I have removed your comments so you can find mine easily 我删除了您的评论,以便您轻松找到我的评论

function onReady() {
  var toDos = [];

  var addToDoForm = document.getElementById('addToDoForm');

  function createNewToDo() {

    var newToDoText = document.getElementById('newToDoText');

    toDos.push({
      title: newToDoText.value,
      complete: false
    });

    newToDoText.value='';
    renderTheUI(toDos);
  }

  function removeToDoItem() {
    // the parameters used here should be defined in any of the parent scopes of this function declaration
    // Example: Following variables are accessible inside this function
    // [toDos, renderTheUI] (created in parent scope of this function "onReady")
    // [onReady] (created in parent scope of onReady "window")
    // but newLi is not defined in any of the parent scopes. So, you should pass newLi as parameter to this function

    // newLi passed as parameter will not have a property toDoList
    newLi.toDoList.removeChild(newLi);
    renderTheUI(toDos);
  }

  function renderTheUI(toDos) {
    var toDoList = document.getElementById('toDoList');

    toDoList.innerHTML = '';

    toDos.forEach(function(toDo) {

      var newLi = document.createElement('li');
      newLi.setAttribute('id', 'myLi');

      var checkbox = document.createElement('input');

      var removeToDo = document.createElement('input');
      removeToDo.setAttribute('type', 'button');
      removeToDo.setAttribute('value', 'remove');
      removeToDo.setAttribute('id', 'removeButton');

      checkbox.type = 'checkbox';

      newLi.innerHTML = toDo.title;

      toDoList.appendChild(newLi);

      newLi.appendChild(checkbox);

      newLi.appendChild(removeToDo);
    });
  }


  addToDoForm.addEventListener('submit', function(event) {
    event.preventDefault();
    createNewToDo();
  });

  // Same as above, removeToDo is not accessible here as is it not defined in the parent scope
  removeToDo.addEventListener('click', function(event) {
    // Here you can access the element the click event is triggered on from "this"
    // You want to remove the "li" element that contains this button
    // You can get it from "this.parentElement", you can pass it to removeToDoItem
    removeToDoItem();
  });

  renderTheUI(toDos);
}
window.onload = function() {
  onReady()
};

I have made the changes to your code and fixed the issues i have mentioned above 我对您的代码进行了更改,并修复了我上面提到的问题

Solution: 解:

 //2) SECOND STEP: build the function that will control everything function onReady() { //2.1) creates and houses the current state of to-do list var toDos = []; //3) THIRD STEP: Event Listener - this accesses the HTML form element var addToDoForm = document.getElementById('addToDoForm'); //2.2) build function that creates/adds list items function createNewToDo() { //2.3) accesses the text input from the form var newToDoText = document.getElementById('newToDoText'); //2.4) adds new item to the toDos array toDos.push({ title: newToDoText.value, complete: false }); //2.5) clears the text in the form input field so user doesn't need to newToDoText.value=''; renderTheUI(toDos); } //8) EIGHT STEP: build function that deletes list item function removeToDoItem(newLi) { var toDoList = newLi.parentElement; // renderTheUI will render the same li again as it is still in the toDos array, you will have to remove the array entry // Get the index of the newLi inside it's parent var index = Array.prototype.indexOf.call(toDoList.children, newLi); // Remove the entry in toDos at that index, we are using same index as li's are the only elements inside toDos toDos.splice(index, 1); // Remove the li element now toDoList.removeChild(newLi); // No need to call the renderTheUI here as the li is already removed and the result would be same // renderTheUI(toDos); } //5) FIFTH STEP: build the function that will render the UI function renderTheUI(toDos) { //5.1) Accesses the <ul> in the HTML var toDoList = document.getElementById('toDoList'); //5.9 sets each newLi to an empty string toDoList.innerHTML = ''; //5.2) Use forEach() array method to render each to-do as an <li> in the <ul> toDos.forEach(function(toDo) { //5.3 creates new <li> var newLi = document.createElement('li'); newLi.setAttribute('id', 'myLi'); //5.4 creates new checkbox var checkbox = document.createElement('input'); //6) SIXTH STEP: create remove button and set its attributes var removeToDo = document.createElement('input'); removeToDo.setAttribute('type', 'button'); removeToDo.setAttribute('value', 'remove'); removeToDo.setAttribute('id', 'removeButton'); //7) SEVENTH STEP: assign remove button event and invoke removeToDoItem() removeToDo.addEventListener('click', function(event) { // You can access newLi here as it is decalred in the parent scope removeToDoItem(newLi); }); //5.5 set var checkbox as a type checkbox checkbox.type = 'checkbox'; //5.6 assigns to-do item to newLi in the HTML newLi.innerHTML = toDo.title; //5.7 appends newLi to the to-do list toDoList.appendChild(newLi); //5.8 appends a checkbox to each newLi newLi.appendChild(checkbox); //6.1 append the remove button to each newLi newLi.appendChild(removeToDo); }); } //3.1) Event Listener - catches 'submit', prevents page reload, // and invokes the function createNewToDo addToDoForm.addEventListener('submit', function(event) { event.preventDefault(); createNewToDo(); }); //4) FOURTH STEP: add the call that controls UI based on state renderTheUI(toDos); } //1) FIRST STEP: invokes the function onReady() when page loads window.onload = function() { onReady() }; 
 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>To-Do App</title> </head> <body> <h1>To-Do App</h1> <form id="addToDoForm"> <label for="newToDoText">New To-Do:</label> <input type="text" id="newToDoText"> <button type="submit">Add To-Do!</button> </form> <ul id="toDoList"> </ul> <script src="app.js"></script> </body> </html> 

EDIT-- A better solution in terms of performance 编辑-性能方面的更好解决方案

//2) SECOND STEP: build the function that will control everything
function onReady() {

  //2.1) creates and houses the current state of to-do list
  var toDos = [];

  //3) THIRD STEP: Event Listener - this accesses the HTML form element
  var addToDoForm = document.getElementById('addToDoForm');

  //2.2) build function that creates/adds list items
  function createNewToDo() {

    //2.3) accesses the text input from the form
    var newToDoText = document.getElementById('newToDoText');

    //2.4) adds new item to the toDos array
    toDos.push({
      title: newToDoText.value,
      complete: false
    });

    //2.5) clears the text in the form input field so user doesn't need to
    newToDoText.value='';

    renderTheUI(toDos);
  }

  //5) FIFTH STEP: build the function that will render the UI
  function renderTheUI(toDos) {

    //5.1) Accesses the <ul> in the HTML
    var toDoList = document.getElementById('toDoList');

    //5.9 sets each newLi to an empty string
    toDoList.innerHTML = '';

    //5.2) Use forEach() array method to render each to-do as an <li> in the <ul>
    toDos.forEach(function(toDo, index) {

      //5.3 creates new <li>
      var newLi = document.createElement('li');
      newLi.setAttribute('id', 'myLi');

      //5.4 creates new checkbox
      var checkbox = document.createElement('input');

      //6) SIXTH STEP: create remove button and set its attributes
      var removeToDo = document.createElement('input');
      removeToDo.setAttribute('type', 'button');
      removeToDo.setAttribute('value', 'remove');
      removeToDo.setAttribute('id', 'removeButton');

      //7) SEVENTH STEP: assign remove button event and invoke removeToDoItem()
      removeToDo.addEventListener('click', function() {
        // Remove the entry in toDos at the index
        toDos.splice(index, 1);
        // Remove the li element
        toDoList.removeChild(newLi);
      });

      //5.5 set var checkbox as a type checkbox
      checkbox.type = 'checkbox';

      //5.6 assigns to-do item to newLi in the HTML
      newLi.innerHTML = toDo.title;

      //5.7 appends newLi to the to-do list
      toDoList.appendChild(newLi);

      //5.8 appends a checkbox to each newLi
      newLi.appendChild(checkbox);

      //6.1 append the remove button to each newLi
      newLi.appendChild(removeToDo);
    });
  }

  //3.1) Event Listener - catches 'submit', prevents page reload,
  // and invokes the function createNewToDo
  addToDoForm.addEventListener('submit', function(event) {
    event.preventDefault();
    createNewToDo();
  });

  //4) FOURTH STEP: add the call that controls UI based on state
  renderTheUI(toDos);
}
//1) FIRST STEP: invokes the function onReady() when page loads
window.onload = function() {
  onReady()
};

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

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