2016-05-05 156 views
2

我在使用parentNode.removeChild()时遇到了一些困难。我在无序列表中列出了“项目”,每个列表都有自己的删除按钮。我试图将一个点击事件绑定到每个单独的按钮,它将删除它的各自父项'项目'。Javascript - 如何使用点击事件和类去除DOM元素?

到目前为止我的代码:

<ul class="list"> 
    <h2>This is a list</h2> 
    <li class="item"> 
    <h3>Some Item</h3> 
    <button class="delete">Delete</div> 
    </li> 
    <li class="item"> 
    <h3>Some Item</h3> 
    <button class="delete">Delete</div> 
    </li> 
    <li class="item"> 
    <h3>Some Item</h3> 
    <button class="delete">Delete</div> 
    </li> 
</ul> 

var childElements = document.getElementsByClassName('item'); 
var buttonElement = document.getElementsByClassName('delete'); 

function deleteItem(buttonsClass, childClass) { 
    for (var i=0;i<buttonsClass.length;i++) { 
    var child = childClass[i]; 
    buttonsClass[i].addEventListener('click', function(child) { 
     childClass[i].parentNode.removeChild(childClass[i]); 
    }, false); 
    }  
} 

deleteItem(buttonElement, childElements); 

我知道有一个简单的方法使用jQuery做到这一点,但我真的想用普通的JavaScript来解决这个问题。感谢您的帮助。

+2

你能描述一下你得到的错误或意外的行为吗? – m69

+1

如果您为该元素分配了一个ID,则更容易删除该元素而不使用for循环; for循环也删除所有元素。 –

回答

1

这是event delegation一个完美的情况下按钮的列表。完全不需要jQuery:

(function(window, htmlElement) { 

    'use strict'; 

    htmlElement.addEventListener("click", handleClick, false); 

    function handleClick(event) { 
     if (event.target.classList.contains("delete")) { 
      event.preventDefault(); 
      removeItem(event.target); 
     } 
    } 

    function removeItem(button) { 
     var item = getItem(button), 
      confirmMessage; 

     if (item) { 
      confirmMessage = item.getAttribute("data-confirm"); 

      if (!confirmMessage || window.confirm(confirmMessage)) { 
       item.parentNode.removeChild(item); 
      } 
     } 
     else { 
      throw new Error("No item found"); 
     } 
    } 

    function getItem(button) { 
     var element = button.parentNode, 
      item = null; 

     while (element) { 
      if (element.nodeName === "LI" || element.nodeName === "TR") { 
       item = element; 
       break; 
      } 

      element = element.parentNode; 
     } 

     return item; 
    } 

})(this, this.document.documentElement); 

无论有多少个删除按钮,您都可以为整个页面设置一个点击处理程序。这也适用于列表项目或表格行,并且通过在按钮上指定data-confirm属性,它将在删除它之前弹出确认框。

<button type="button" class="delete" 
     data-confirm="Are you sure you want to delete this item?"> 
    Delete 
</button> 

你也可以很容易地改变这种做法,它使用另一个属性,找到删除按钮:

<button type="button" class="delete" 
     data-delete 
     data-confirm="..."> 
    Delete 
</button> 

只要改变if语句的条件在handleClick功能:

if (event.target.hasAttribute("data-delete")) { 
    event.preventDefault(); 
    removeItem(event.target); 
} 

这使您的行为与造型脱钩。您可以使用delete类名称进行样式设置,并使用data-delete属性进行JavaScript行为。如果您因任何原因需要更改CSS删除类的名称,或者使用其他类,因为您决定使用第三方CSS框架(如Bootstrap),则不需要更改一行JavaScript。

这里的最后一个优点是点击处理程序连接到document.documentElement对象,该对象在JavaScript开始执行时可用并表示<html>元素。不需要jQuery的文档就绪事件处理程序。只需附加点击处理程序并在页面上的任意位置导入脚本。

+0

谢谢,这是一个非常优雅的解决方案,完全符合我的要求。复杂性略高于我的技能水平,但现在我知道它的工作原理,我可以剖析它的组成部分,直到我明白它的作用。那么我会尝试它作为一个对象的方法。 –

+0

附录中关于事件委派的文章确实很有帮助。谢谢! –

+0

我无法找到您在classList对象上使用的“contains”方法的任何引用。这种方法来自哪里? –

2

问题是当您单击元素时调用的您的childClass[i]不是您在定义函数时所期望的。 您应该使用event.target为赶上元素点击

var childElements = document.getElementsByClassName('item'); 
var buttonElement = document.getElementsByClassName('delete'); 

var _handler = function(e) { 
    e.target.parentNode.parentNode.removeChild(e.target.parentNode); 
} 

function deleteItem(buttonsClass, childClass) { 
    for (var i=0;i<buttonsClass.length;i++) { 
    buttonsClass[i].addEventListener('click', _handler, false); 
    }  
} 

deleteItem(buttonElement, childElements); 

- 编辑 -

如果你想使用原来的做法,那么你可以用这种方式解决它:

function deleteItem(buttonsClass, childClass) { 
    for (var i=0;i<buttonsClass.length;i++) { 
    (function(child) { 
     buttonsClass[i].addEventListener('click', function(e) { 
      child.parentNode.removeChild(child); 
     }, false); 
    })(childClass[i]); 
    }  
} 

使用封装(function(encapsulatedChild) { })(child)您可以将子值存储在上下文中不会更改的上下文中。

+0

问题,使用你的封装方法。 “孩子”的论点是指什么? –

+1

你用'(function(arg){...})创建一个函数',然后立即传递你想要的参数'(childClass [i])'。通过这种方式,你的childClass [i]引用被复制到'child' var。这个变量只在函数的上下文中,所以在下一个循环中它不会被覆盖 –

1

看起来你想绑定一个点击事件来删除按钮,并在该事件中删除该项目。

您需要获取子类个人buttonsClass元素。

function deleteItem(childElements) 
{ 
    Array.prototype.slice.call(childElements).forEach(function(item){ 
     var deleteChildren = item.getElementsByClassName("delete"); 
     Array.prototype.slice.call(deleteChildren).forEach(function(deleteBtn){ 
     deleteBtn.addEventListener('click', function() 
     { 
      this.parentNode.removeChild(this); 
     }, false);   
     }); 
    }); 
} 

,甚至更简单,只是通过在点击其母公司item将被删除

function deleteItem(buttonElement) 
{ 
    Array.prototype.slice.call(buttonElement).forEach(function(button){ 
     button.addEventListener('click', function() 
     { 
      this.parentNode.removeChild(this); 
     }, false);   
    }); 
} 
相关问题