如何使用所述列表项上的按钮删除列表项

How to remove list item using button on said list item

我正在构建一个待办事项列表,但我无法弄清楚删除功能。我不断收到一条错误消息,指出 "Node not found".

大部分都是我自己编写的,但我查找了这部分的教程。他们建议使用:

function removeItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
parent.removeChild(item);
};

我试图将它应用到我已有的代码中,但它似乎不起作用。 我也不完全清楚以下逻辑:

var item = this.parentNode.parentNode;
var parent = this.parentNode;

如果有人也可以解释它的作用,我们将不胜感激。

HTML:

<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="resources/css/styles.css">
  </head>
<body>

<header id="addtodo">

  <input type="text" id="input" placeholder="Add an item"/>
  <button id="button"  type="button">Add item</button>
</header>

  <div id="listcontainer">
    <ul id="itemlist">

    </ul>
  </div>

  <div id="dividerline">

  </div>

  <div id="completecontainer">
    <ul id="completed">

    </ul>
  </div>



    <script src="resources/JS/code.js"></script>
  </body>

JavaScript:

document.getElementById('button').addEventListener('click', function(){
var value = document.getElementById('input').value;

var item = document.createElement("li");

var itemText = document.createTextNode(value);

var itemdiv= document.createElement('div');
var buttons=document.createElement('div');
var text=document.createElement('div');

var remove = document.createElement("button");
var complete = document.createElement("button");
var itemlist = document.getElementById('itemlist');




item.appendChild(itemdiv);
itemdiv.appendChild(text);
text.appendChild(itemText);
itemdiv.appendChild(buttons);
buttons.appendChild(complete);
buttons.appendChild(remove);

remove.innerHTML = 'Remove';
complete.innerHTML = 'Complete';

remove.classList.add('remove');
remove.setAttribute('id','remove');

complete.classList.add('complete');
complete.setAttribute('id','complete');

buttons.classList.add('buttondiv');
text.classList.add('text');
itemdiv.classList.add('itemdiv');

remove.addEventListener('click', removeItem);
complete.addEventListener('click', completeItem);

itemlist.insertBefore(item, itemlist.childNodes[0]);
});


function removeItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
parent.removeChild(item);
};

function completeItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
parent.removeChild(item);
};

我想要删除按钮删除它所附加的列表项。

错误在函数中

function completeItem() {
  var item = this.parentNode.parentNode;
  var parent = this.parentNode;
  parent.removeChild(item);
};

交换 itemparent,像这样:parent.removeChild(item);

首先,使用console.log()函数来调试你的代码:

  function removeItem() {
    var item = this.parentNode.parentNode;
    var parent = this.parentNode;
    console.log( 'item', item ); // => <div class="itemdiv">
    console.log( 'parent', parent ); // => <div class="buttondiv">
    parent.removeChild(item);
  };

如您所见:
1) 你混淆了项目和父节点。
2)如果你想删除整个<li>元素,你必须使用更多parentNode

function removeItem() {
  var parent = this.parentNode.parentNode.parentNode.parentNode;
  var item = this.parentNode.parentNode.parentNode;
  console.log( 'item', item ); // => <li>
  console.log( 'parent', parent ); // => <ul id="itemlist">
  parent.removeChild(item);
};

或直接在您的项目上调用 remove() 方法:

function removeItem() {
  var item = this.parentNode.parentNode.parentNode;
  item.remove();
};

但最好的方法是使用 closest() 方法:

function removeItem() {
  var item = this.closest( 'li' );
  item.remove();
};

最简单的解决方案是忘记 parentNode,只给新的 <li> 一个唯一的 class。然后,您可以使用 closest() 方法删除 <li>

此外,您正在创建一些不必要的节点,并且确实应该更具描述性地命名变量。

此外,您不能有多个具有相同 id 的元素,坦率地说,您不需要新元素首先具有 id,所以忘记这一点。

最后,在继续下一个元素之前完成新元素的所有创建和配置。它使代码更易于阅读,并防止您忘记配置。

var list = document.getElementById("itemlist");
var todo = document.getElementById('input');

document.getElementById('button').addEventListener('click', function(){

  var li = document.createElement("li");
  li.textContent = todo.value;
  li.classList.add("container");

  var itemDiv= document.createElement('div');
  var buttonDiv=document.createElement('div');

  var removeBtn = document.createElement("button");
  removeBtn.textContent = 'Remove';
  removeBtn.addEventListener('click', removeItem);
  removeBtn.classList.add('remove');
  
  var completeBtn = document.createElement("button");
  completeBtn.textContent = 'Complete';
  completeBtn.addEventListener('click', completeItem);
  completeBtn.classList.add('complete');

  // Append your items from the inside out
  buttonDiv.appendChild(completeBtn);
  buttonDiv.appendChild(removeBtn);
  itemDiv.appendChild(buttonDiv);
  li.appendChild(itemDiv);

  list.insertBefore(li, list.childNodes[0]);
});


function removeItem() {
  //Just find the closese ancestor that matches the selector and remove it
  this.closest(".container").remove();
};

function completeItem() {
var item = this.parentNode.parentNode;
var parent = this.parentNode;
parent.removeChild(item);
};
<header id="addtodo">

  <input type="text" id="input" placeholder="Add an item"/>
  <button id="button"  type="button">Add item</button>
</header>

  <div id="listcontainer">
    <ul id="itemlist">

    </ul>
  </div>

  <div id="dividerline">

  </div>

  <div id="completecontainer">
    <ul id="completed">

    </ul>
  </div>

问题在于您如何尝试从父函数中捕获列表项。 this.parentNode.parentNode 获取按钮所在的 div 项。调用 item.parentNode 获取外部列表项对象,而不是从父项中删除项,只需删除整个列表项

document.getElementById('button').addEventListener('click', function(e){
 var value = document.getElementById('input').value;

 var item = document.createElement("li");

  var itemText = document.createTextNode(value);

  var itemdiv= document.createElement('div');
  var buttons=document.createElement('div');
  var text=document.createElement('div');

  var remove = document.createElement("button");
  var complete = document.createElement("button");
  var itemlist = document.getElementById('itemlist');

  item.appendChild(itemdiv);
  itemdiv.appendChild(text);
  text.appendChild(itemText);
  itemdiv.appendChild(buttons);
  buttons.appendChild(complete);
  buttons.appendChild(remove);

  remove.innerHTML = 'Remove';
  complete.innerHTML = 'Complete';

  remove.classList.add('remove');
  remove.setAttribute('id','remove');

  complete.classList.add('complete');
  complete.setAttribute('id','complete');

  buttons.classList.add('buttondiv');
  text.classList.add('text');
  itemdiv.classList.add('itemdiv');

  remove.addEventListener('click', removeItem);
  complete.addEventListener('click', completeItem);

  itemlist.insertBefore(item, itemlist.childNodes[0]);
});


function removeItem() {
  var item = this.parentNode.parentNode;
  var parent = item.parentNode;
  parent.remove()
};

function completeItem() {
  var item = this.parentNode.parentNode;
  var parent = item.parentNode;
  
  parent.remove()
};
<header id="addtodo">

  <input type="text" id="input" placeholder="Add an item"/>
  <button id="button"  type="button">Add item</button>
</header>

  <div id="listcontainer">
    <ul id="itemlist">

    </ul>
  </div>

  <div id="dividerline">

  </div>

  <div id="completecontainer">
    <ul id="completed">

    </ul>
  </div>

对于这种情况,箭头函数是最简单的方法:(以及克隆节点)

const myButton       = document.getElementById('my-button')
    , textInput      = document.getElementById('text-input')
    , ListItems      = document.getElementById('itemlist')
    , LI_clone4Items = document.querySelector('#clone4Items > li')

var count = 0

myButton.onclick=_=>
{
  let newLI = LI_clone4Items.cloneNode(true)
  ListItems.insertBefore(newLI, ListItems.childNodes[0])
  newLI.querySelector('.text').textContent = textInput.value
  newLI.querySelector('.complete').onclick =_=> { ListItems.removeChild(newLI) }
  newLI.querySelector('.remove').onclick   =_=> { ListItems.removeChild(newLI) }
  textInput.value = ''
  myButton.disabled = true
}

(textInputControl =_=> { myButton.disabled = (textInput.value.trim()==='') })()

textInput.oninput = textInputControl
<header id="addtodo">
  <input type="text" id="text-input" placeholder="Add an item" />
  <button id="my-button" type="button">Add item</button>
</header>

<div id="listcontainer">
  <ul id="itemlist"></ul>
</div>

<div id="dividerline">
</div>

<div id="completecontainer">
  <ul id="completed"></ul>
</div>

<!-- hidden -->
<div style="display:none">
  <ul id="clone4Items">
    <li>
      <div class="itemdiv">
        <div class="text"></div>
        <div class="buttondiv">
          <button class="complete" >Complete</button>
          <button class="remove" >Remove</button>
        </div>
      </div>
    </li>
  </ul>