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

时间:2017-10-01 18:32:06

标签: javascript

首先我要说:

  1. 我已经查看了很多关于解决这个问题的文档 问题
  2. 我仍然是JavaScript的新手。
  3. 问题:删除按钮不会删除相应的内容,即li项。对我而言,这意味着问题出在第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()
    };
    &#13;
    <!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>
    &#13;
    &#13;
    &#13;

2 个答案:

答案 0 :(得分:0)

您正在绑定click事件侦听器以removeToDo,而removeToDo仅存在于renderUI函数内。所以你的第七步是错的。 你需要在createUI中添加Event监听器。用以下代码替换脚本

//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();

答案 1 :(得分:0)

您的代码中存在一些错误,我在下面使用注释对其进行了解释。 我已删除您的评论,以便您轻松找到我的

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()
};

我已对代码进行了更改并修复了上面提到的问题

<强>解决方案:

&#13;
&#13;
//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()
};
&#13;
<!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>
&#13;
&#13;
&#13;

编辑 - 在性能方面更好的解决方案

//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()
};