首页 > 解决方案 > 我不知道在这种情况下如何使用 ForEach

问题描述

在我的应用程序中,我不确定如何正确使用 ForEach 循环。

请写一些文字输入并按回车,任务将被添加到列表中。这是 addNewTask() 函数。您可以通过单击编辑图标来编辑任务,但只能编辑一次。我理解为什么,因为 ForEach 在 addNewTask() 中,好吧,所以,如果调用函数,每个任务我只能编辑一次。我想我需要为这种情况创建一个函数?但我不知道如何使用它。

var editTask = document.querySelectorAll('.edit-task'); 在这个变量中是编辑任务图标。

如果我尝试使用例如editTask.addEvenetListener("click", function() { ... })输出将是错误的,因为 edittask 返回节点列表。有什么简单的解决办法吗?我不知道该怎么办。

JS 代码从这一行开始 -> var editTask = document.querySelectorAll('.edit-task');

'use strict';

var todoTitle = document.querySelector('.title-input');
var todoList = document.querySelector('.todo-list');

function formatDate(date) {
    var monthNames = [
      "January", "February", "March",
      "April", "May", "June", "July",
      "August", "September", "October",
      "November", "December"
    ];
  
    var day = date.getDate();
    var monthIndex = date.getMonth();
    var year = date.getFullYear();
    var hours = date.getHours();
    var mins = date.getMinutes();
  
    return day + ' ' + monthNames[monthIndex] + ' ' + year + ', ' + hours 
+ ':' + mins;
}

function createNewTask(task) {
    var listItem = document.createElement('li');
    var textItem = document.createElement('div');
    var dateInfo = document.createElement('span');
    var icons = document.createElement('div');
    // var saveEditedTask = document.createElement('span');

var iconsClass = [
    '<i class="fas fa-tag"></i>',
    '<i class="fas fa-palette change-bgcolor"></i>',
    '<i class="fas fa-edit edit-task"></i>',
    '<i class="fas fa-check-square"></i>',
    '<i class="fas fa-times-circle delete-task"></i>'
]

iconsClass.forEach(function(icon) {

    var iconParent = document.createElement('li');
    iconParent.className = 'icon-item';
    iconParent.innerHTML = icon;
    icons.appendChild(iconParent);
    
});

dateInfo.innerText = formatDate(new Date());
dateInfo.className = 'task-date';
textItem.className = 'list-content';
icons.className = 'action-icons';
textItem.innerText = task;
listItem.className = 'list-item';
// textItem.appendChild(icons);
listItem.appendChild(textItem);
// listItem.appendChild(saveEditedTask);
listItem.appendChild(icons);
listItem.appendChild(dateInfo);

return listItem;

};

function addNewTask() {
    var listItem = createNewTask(todoTitle.value);
    todoList.appendChild(listItem);
    todoTitle.value = '';

    var deleteTask = document.querySelectorAll('.delete-task');

    deleteTask.forEach(function (icon) {
        icon.addEventListener("click", function() {
        this.closest("li.list-item").classList.add("hidden");     
        });
    });

    var editTask = document.querySelectorAll('.edit-task');

    editTask.forEach(function (icon) {
        icon.addEventListener("click", function () {
            var thisParent = 
    this.parentElement.parentElement.previousElementSibling;
            thisParent.contentEditable = true;
            thisParent.style.backgroundColor = "#efefef";
            this.classList.remove("fas", "fa-edit", "edit-task");
            this.classList.add("fas", "fa-check", "fa-2x");
        
            this.addEventListener("click", function () {
                thisParent.contentEditable = false;
                thisParent.style.backgroundColor = "#ffffff";
                this.classList.remove("fas", "fa-check", "fa-2x");
                this.classList.add("fas", "fa-edit", "edit-task");
            })
        })
    });

};

    todoTitle.addEventListener('keyup', function (event) {
        if (event.keyCode === 13 && todoTitle.value.length >= 1) {
            addNewTask();
        }
    });
* {
    -webkit-box-sizing: border-box;
            box-sizing: border-box;
}

body {
    font-family: 'Ubuntu', sans-serif;
    font-weight: 400;
    font-size: 100%;
    width: 100%;
    height: 100%;
    overflow-x: hidden;
    margin: 0;
    padding: 0;
}

#todoapp {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0px 20px;
}

input.title-input {
    -webkit-transition: all.5s;
    -webkit-transition: all .5s;
    transition: all .5s;
    display: block;
    width: 200px;
    margin: 10px 0;
    padding: 5px 15px;
    border: none;
    border-bottom: 1px solid #ccc;
    outline: none;
    position: relative;
    top: 0;
    left: 50%;
    -webkit-transform: translate(-50%, 0);
            transform: translate(-50%, 0);
    margin-bottom: 50px;
}

input.title-input:focus {
    width: 100%;
    -webkit-box-shadow: 0px 5px 20px 0px rgba(0,0,0,0.75);
            box-shadow: 0px 5px 20px 0px rgba(0,0,0,0.75);
    border-bottom: none;
    border-radius: 15px;
    font-size: 16px;
    padding: 10px 20px;
}


.todo-list {
    list-style-type: none;
    padding: 0;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
        -ms-flex-flow: row wrap;
            flex-flow: row wrap;
    -webkit-box-align: start;
        -ms-flex-align: start;
            align-items: flex-start;
    -webkit-box-pack: start;
        -ms-flex-pack: start;
            justify-content: flex-start;
}

.todo-list .list-item {
    padding: 15px;
    padding-bottom: 5px;
    background-color: #ffffff;
    border: 1px solid #e0e0e0;
    border-radius: 10px;
    color: #202124;
    margin-bottom: 10px;
    /* min-heiglist-coht: 100px; */
    width: 200px;
    position: relative;
    margin: 5px;
    -webkit-transition: all .25s;
    transition: all .25s;
}

.todo-list .list-item .bg-colors {
    width: 105px;
    height: auto;
    /* height: 100px; */
    background-color: #ffffff;
    position: absolute;
    bottom: 30px;
    left: 0;
    right: 0;
    -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.25);
    box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.25);

    /* display: none; */
}

.todo-list .list-item .bg-colors span {
    width: 25px;
    height: 25px;
    /* background-color: #ffffff; */
    display: inline-block;
    margin: 5px;
    border-radius: 50%;
    border: 1px solid #ccc;
}

.todo-list .list-item .bg-colors span:hover {
    border-color: #000000;
}

.todo-list .list-item:hover {
    -webkit-box-shadow: 0px 5px 5px 0px rgba(0,0,0,0.25);
            box-shadow: 0px 5px 5px 0px rgba(0,0,0,0.25);
}

.todo-list .list-item:hover .action-icons {
    opacity: 1;
}

.todo-list .list-item .list-content {
    position: relative;
    min-height: 150px;
    padding: 5px;
}

.todo-list .list-item .task-date {
    font-size: 12px;
    display: block;
    text-align: right;
    padding-top: 10px;
    padding-bottom: 5px;
    border-top: 1px solid #e0e0e0;
}

.todo-list .list-item .action-icons {
    position: relative;
    bottom: 0;
    right: 0;
    left: 0;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-pack: distribute;
        justify-content: space-around;
        -webkit-box-align: center;
            -ms-flex-align: center;
                align-items: center;
    margin: 10px 0;
    /* opacity: 0; */
    -webkit-transition: all .25s;
    transition: all .25s;
}

.todo-list .list-item .action-icons .icon-item {
    display: inline-block;
    cursor: pointer;
}

.hidden { display:none !important; }

.visible { display: block !important; }

.fas.fa-check {
    color: green;
}
<link rel="stylesheet" 
href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" 
integrity="sha384- 
oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" 
crossorigin="anonymous">

<div id="todoapp">
    <input type="text" class="title-input" placeholder="Write a note..">
    <ul class="todo-list"></ul>
</div>

标签: javascripthtmlcss

解决方案


您的代码中有一些逻辑错误。

在您的addNewTask()函数中,您执行以下代码:

    var editTask = document.querySelectorAll('.edit-task');

    editTask.forEach(function (icon) {
..
}

这意味着每次添加任务时,每个先前的任务都会获得点击侦听器并重新添加所有内容。

而是使用以下方法获取对在新生成的任务中实际使用类编辑任务的元素的引用:

var icon = listItem.getElementsByClassName("edit-task")[0];

这将返回一个 HTML 集合——它只包含我们使用[0]访问的一个元素。

下一个问题是您附加点击事件侦听器的方式:

   editTask.forEach(function(icon) {
     icon.addEventListener("click", function() {
       var thisParent =
         this.parentElement.parentElement.previousElementSibling;
       thisParent.contentEditable = true;
       thisParent.style.backgroundColor = "#efefef";
       this.classList.remove("fas", "fa-edit", "edit-task");
       this.classList.add("fas", "fa-check", "fa-2x");

       this.addEventListener("click", function() {
         thisParent.contentEditable = false;
         thisParent.style.backgroundColor = "#ffffff";
         this.classList.remove("fas", "fa-check", "fa-2x");
         this.classList.add("fas", "fa-edit", "edit-task");
       })
     })
   });

上面的意思是每次单击图标时都会添加另一个单击侦听器。这些相互干扰并将您的文本字段重置为不可编辑。最好这样做:在createNewTask()函数中,将 div textItem的 contentEditable 属性设置为 false

textItem.contentEditable = false;

这样我们就可以在 click 事件处理程序中检查这个值并采取相应的行动。如果它是假的,让它成为真的,反之亦然。

  icon.addEventListener("click", function() {
    var thisParent =
      this.parentElement.parentElement.previousElementSibling;
    switch (thisParent.contentEditable) {
      case "false":
        thisParent.contentEditable = true;
        thisParent.style.backgroundColor = "#efefef";
        this.classList.remove("fas", "fa-edit", "edit-task");
        this.classList.add("fas", "fa-check", "fa-2x");
        break;
      case "true":
        thisParent.contentEditable = false;
        thisParent.style.backgroundColor = "#ffffff";
        this.classList.remove("fas", "fa-check", "fa-2x");
        this.classList.add("fas", "fa-edit", "edit-task");
        break;
    }
  });

这是完整的示例:

'use strict';

var todoTitle = document.querySelector('.title-input');
var todoList = document.querySelector('.todo-list');

function formatDate(date) {
  var monthNames = [
    "January", "February", "March",
    "April", "May", "June", "July",
    "August", "September", "October",
    "November", "December"
  ];

  var day = date.getDate();
  var monthIndex = date.getMonth();
  var year = date.getFullYear();
  var hours = date.getHours();
  var mins = date.getMinutes();

  return day + ' ' + monthNames[monthIndex] + ' ' + year + ', ' + hours +
    ':' + mins;
}

function createNewTask(task) {
  var listItem = document.createElement('li');
  var textItem = document.createElement('div');
  var dateInfo = document.createElement('span');
  var icons = document.createElement('div');
  // var saveEditedTask = document.createElement('span');

  var iconsClass = [
    '<i class="fas fa-tag"></i>',
    '<i class="fas fa-palette change-bgcolor"></i>',
    '<i class="fas fa-edit edit-task"></i>',
    '<i class="fas fa-check-square"></i>',
    '<i class="fas fa-times-circle delete-task"></i>'
  ]

  iconsClass.forEach(function(icon) {

    var iconParent = document.createElement('li');
    iconParent.className = 'icon-item';
    iconParent.innerHTML = icon;
    icons.appendChild(iconParent);

  });

  dateInfo.innerText = formatDate(new Date());
  dateInfo.className = 'task-date';
  textItem.className = 'list-content';
  textItem.contentEditable = false;
  icons.className = 'action-icons';
  textItem.innerText = task;
  listItem.className = 'list-item';
  // textItem.appendChild(icons);
  listItem.appendChild(textItem);
  // listItem.appendChild(saveEditedTask);
  listItem.appendChild(icons);
  listItem.appendChild(dateInfo);

  return listItem;

}

function addNewTask() {
  var listItem = createNewTask(todoTitle.value);

  todoList.appendChild(listItem);
  todoTitle.value = '';

  var deleteTask = document.querySelectorAll('.delete-task');

  deleteTask.forEach(function(icon) {
    icon.addEventListener("click", function() {
      this.closest("li.list-item").classList.add("hidden");
    });
  });

  var editTask = document.querySelectorAll('.edit-task');

  var icon = listItem.getElementsByClassName("edit-task")[0];

  icon.addEventListener("click", function() {
    var thisParent =
      this.parentElement.parentElement.previousElementSibling;
    switch (thisParent.contentEditable) {
      case "false":
        thisParent.contentEditable = true;
        thisParent.style.backgroundColor = "#efefef";
        this.classList.remove("fas", "fa-edit", "edit-task");
        this.classList.add("fas", "fa-check", "fa-2x");
        break;
      case "true":
        thisParent.contentEditable = false;
        thisParent.style.backgroundColor = "#ffffff";
        this.classList.remove("fas", "fa-check", "fa-2x");
        this.classList.add("fas", "fa-edit", "edit-task");
        break;
    }
  });
};

todoTitle.addEventListener('keyup', function(event) {
  if (event.keyCode === 13 && todoTitle.value.length >= 1) {
    addNewTask();
  }
});
* {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  font-family: 'Ubuntu', sans-serif;
  font-weight: 400;
  font-size: 100%;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  margin: 0;
  padding: 0;
}

#todoapp {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0px 20px;
}

input.title-input {
  -webkit-transition: all.5s;
  -webkit-transition: all .5s;
  transition: all .5s;
  display: block;
  width: 200px;
  margin: 10px 0;
  padding: 5px 15px;
  border: none;
  border-bottom: 1px solid #ccc;
  outline: none;
  position: relative;
  top: 0;
  left: 50%;
  -webkit-transform: translate(-50%, 0);
  transform: translate(-50%, 0);
  margin-bottom: 50px;
}

input.title-input:focus {
  width: 100%;
  -webkit-box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.75);
  box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.75);
  border-bottom: none;
  border-radius: 15px;
  font-size: 16px;
  padding: 10px 20px;
}

.todo-list {
  list-style-type: none;
  padding: 0;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
  -webkit-box-align: start;
  -ms-flex-align: start;
  align-items: flex-start;
  -webkit-box-pack: start;
  -ms-flex-pack: start;
  justify-content: flex-start;
}

.todo-list .list-item {
  padding: 15px;
  padding-bottom: 5px;
  background-color: #ffffff;
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  color: #202124;
  margin-bottom: 10px;
  /* min-heiglist-coht: 100px; */
  width: 200px;
  position: relative;
  margin: 5px;
  -webkit-transition: all .25s;
  transition: all .25s;
}

.todo-list .list-item .bg-colors {
  width: 105px;
  height: auto;
  /* height: 100px; */
  background-color: #ffffff;
  position: absolute;
  bottom: 30px;
  left: 0;
  right: 0;
  -webkit-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.25);
  box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.25);
  /* display: none; */
}

.todo-list .list-item .bg-colors span {
  width: 25px;
  height: 25px;
  /* background-color: #ffffff; */
  display: inline-block;
  margin: 5px;
  border-radius: 50%;
  border: 1px solid #ccc;
}

.todo-list .list-item .bg-colors span:hover {
  border-color: #000000;
}

.todo-list .list-item:hover {
  -webkit-box-shadow: 0px 5px 5px 0px rgba(0, 0, 0, 0.25);
  box-shadow: 0px 5px 5px 0px rgba(0, 0, 0, 0.25);
}

.todo-list .list-item:hover .action-icons {
  opacity: 1;
}

.todo-list .list-item .list-content {
  position: relative;
  min-height: 150px;
  padding: 5px;
}

.todo-list .list-item .task-date {
  font-size: 12px;
  display: block;
  text-align: right;
  padding-top: 10px;
  padding-bottom: 5px;
  border-top: 1px solid #e0e0e0;
}

.todo-list .list-item .action-icons {
  position: relative;
  bottom: 0;
  right: 0;
  left: 0;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-pack: distribute;
  justify-content: space-around;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  margin: 10px 0;
  /* opacity: 0; */
  -webkit-transition: all .25s;
  transition: all .25s;
}

.todo-list .list-item .action-icons .icon-item {
  display: inline-block;
  cursor: pointer;
}

.hidden {
  display: none !important;
}

.visible {
  display: block !important;
}

.fas.fa-check {
  color: green;
}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" integrity="sha384- 
oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">

<div id="todoapp">
  <input type="text" class="title-input" placeholder="Write a note..">
  <ul class="todo-list"></ul>
</div>


推荐阅读