单击时从数组中删除对象

时间:2020-07-14 11:28:33

标签: javascript arrays object

我需要从数组中删除对象的帮助。

对象中的名称(array.name)显示在DOM中,我想使用“擦除X”按钮将其删除。

在此代码中,我只能删除一个元素,然后在没有控制台错误的情况下停止工作。 有谁知道我错了,为什么我每次单击擦除按钮时都不能调用create()函数。

看console.log ...它显示了要删除的元素的良好位置和名称,但是当我调用create()函数并取消注释create()时,一切都停止了。

const array = [ {name: 'John'}, {name: 'David'}, {name: 'Peter'}, {name: 'Michael'} ]; 

const create = () => {
    const app = document.querySelector('.app');
    app.innerHTML = '';

    for(let i = 0; i < array.length; i++) {
      app.innerHTML += `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`;
    }
}
create();

const erase = document.querySelectorAll('.erase');

erase.forEach(item => {
    item.onclick = () => {
      const itemText = item.parentElement.textContent.substr(1);
      const itemPos = array.findIndex(item => item.name == itemText);
    
        console.log(itemText + ' ' + itemPos);
        console.log(array);
        array.splice(itemPos, 1);
        //create()
    }
});
.erase {
  color: red;
  margin-right: 20px;
  cursor: pointer;
}

.item {
  margin-bottom: 10px;
}
<div class="app"></div>

或者作为小提琴:https://jsfiddle.net/05cwy9d2/3/

6 个答案:

答案 0 :(得分:3)

这是因为在dom中创建新元素时,旧元素的侦听器会与旧元素一起被删除。只需将事件侦听器注册移到create方法中即可。

const array = [
  {name: 'John'},
  {name: 'David'},
  {name: 'Peter'},
  {name: 'Michael'}
]; 

const create = () => {
  const app = document.querySelector('.app');
  app.innerHTML = '';

  for(let i=0;i<array.length;i++){
    app.innerHTML += 
      `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`;
  }

  const erase = document.querySelectorAll('.erase');

  erase.forEach(item => {
    item.onclick = () => {
      const itemText = item.parentElement.textContent.substr(1);
      const itemPos = array.findIndex(item => item.name == itemText);


      console.log(itemText + ' ' + itemPos);
      console.log(array);
      array.splice(itemPos, 1);
      create();
    }
  });
}

create();
.erase{
color: red;
margin-right: 20px;
cursor: pointer;
}
.item{
margin-bottom: 10px;
}
<div class="app"></div>

答案 1 :(得分:1)

const array = [
  {name: 'John'},
  {name: 'David'},
  {name: 'Peter'},
  {name: 'Michael'}
]; 

const create = () => {
    const app = document.querySelector('.app');
    app.innerHTML = '';

    for(let i=0;i<array.length;i++){
      app.innerHTML += 
      `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`;
    }
}
create();

const erase = document.querySelectorAll('.erase');

erase.forEach(item => {

    item.onclick = () => {
      const itemText = item.parentElement.textContent.substr(1);
      const itemPos = array.findIndex(item => item.name == itemText);
    
        console.log(itemText + ' ' + itemPos);
        
        if(itemPos >-1){
            array.splice(itemPos, 1);
            item.parentElement.remove();
        }
        console.log(array);
    }
});

现在可以使用。单击删除时已删除DOM,并禁止用户删除已删除的元素(如果index == -1)。

答案 2 :(得分:0)

您只需要删除dom元素

full_join

https://jsfiddle.net/tLk5vmy0/

答案 3 :(得分:0)

我将事件侦听器代码移至create函数,因为需要在一个事件发生时重新创建。您还可以使用EventTarget.addEventListener()方法将事件侦听器绑定到每个单个DOM元素。

我也更愿意使用Array.prototype.filter()方法删除点击的值,以提高可读性:

let array = [
  {name: 'John'},
  {name: 'David'},
  {name: 'Peter'},
  {name: 'Michael'}
]; 

const addEventListeners = () => {
  const erase = document.querySelectorAll('.erase');
  erase.forEach(item => {
    item.onclick = (e) => {
        const itemText = item.parentElement.textContent.substr(1);
        array = array.filter(entry => entry.name !== itemText);
        create();
    }
  });
}

const create = () => {
    const app = document.querySelector('.app');
    app.innerHTML = '';

    for(let i=0;i<array.length;i++){
      app.innerHTML += 
      `<div class="item"><span class="erase">&#9747;</span>${array[i].name}</div>`;
    }
    addEventListeners();
}
create();
<div class="app"></div>

答案 4 :(得分:0)

您可以使用方法removeChild从DOM中删除元素,这样可以防止每次从数组中删除项目时都重新渲染(使用 create 方法) 。这样,您的代码将需要进行一些更改,第一个更改是为数组的每个元素都有一个ID:

for(let person of array){
  app.innerHTML += 
  `<div class="item" id="${person.name}"><span class="erase">&#9747;</span>${person.name}</div>`;
}

将“人员”名称作为ID(我建议您使用一个真实的标识符,例如数字,但在此示例中,名称将对我们有帮助),您只能将该节点从DOM中删除:

const elementToRemove = document.getElementById(item.parentElement.id);
elementToRemove.parentNode.removeChild(elementToRemove);

要增强功能,您可以检查节点是否存在,如果不存在,则可以向控制台抛出错误:

const elementToRemove = document.getElementById(item.parentElement.id);

if (!elementToRemove) throw new Error(`Element ${item.parentElement.id} not found!`)

elementToRemove.parentNode.removeChild(elementToRemove)

我建议您阅读Node section on MDN,这对于将其他元素添加到列表,编辑某些元素等等很有用。 :)

答案 5 :(得分:0)

您将使用item.parentElement.remove()来代替再次调用create()函数并为类'.app'创建新的子元素;代替onClick中的create()。那会得到相同的结果。

erase.forEach(item => {

item.onclick = () => {
 console.log()
  const itemText = item.parentElement.textContent.substr(1);
  const itemPos = array.findIndex(item => item.name == itemText);

    console.log(itemText + ' ' + itemPos);
    console.log(array);
    array.splice(itemPos, 1);
   item.parentElement.remove(); // this will remove your element.
  // create();
  
}

});