【问题标题】:How to assign a javascript function by classname如何通过类名分配 javascript 函数
【发布时间】:2016-05-08 21:15:26
【问题描述】:

我有多个按钮(由 php 生成)用于购物车应用程序:

<button class="addtocart" id="<?php echo $code; ?>"> 
    <span id="addtocartbutton">Add to cart</span>
</button>

我想使用函数更新我的购物车:

function AddtoCart() {
    alert("Added!");
}

稍后,我想找到由调用它的按钮创建的 id ($code)(也不知道该怎么做,但也许这是另一个问题)。所以我尝试了这个:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart());

但它不起作用。它正在使用 onclick 工作,但我知道通过创建 EventListener 来做到这一点的正确方法。另外,我不能在 jQuery 中使用 on() 函数,因为我不得不使用没有它的 jQuery 版本 1.6。

我查看了https://stackoverflow.com/a/25387857/989468,我不能真正将它分配给作为p标签的父级,因为我显然不希望p标签中的其他元素被分配这个功能。

【问题讨论】:

  • 我们可以在按钮中添加id
  • 我的意思是名称属性
  • IIRC,jQuery 1.6 有 .live.on 基本相同。
  • 在 jquery 1.6 中使用 .delegate().bind() (视情况而定)而不是 .on() - 你没有用“jquery”标记问题,但是你提到你是使用它,所以你不妨用它来解决这个问题,以节省一些精力。

标签: javascript addeventlistener


【解决方案1】:

我将展示您在代码中遇到的一些错误,然后向您展示如何改进它以实现您想要的效果,并且我还将展示它可以与稍后动态添加的按钮一起使用:

首先,您需要将函数引用(它的名称)传递给addEventListener!您已经调用了该函数,并传递了它返回的任何内容。而不是:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart());

应该是这样的:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart);

第二个:document.getElementsByClassName("addtocart")返回一个NodeList,你不能操作它,你需要操作它的元素:document.getElementsByClassName("addtocart")[0], [1],...

第三,我建议你使用data-... html 属性:

<button class="addtocart" id="addtocart" data-foo="<? echo $code; ?>">

这样您可以传递更多数据。现在您可以将$code 获取为:

document.getElementById('addtocart').dataset.foo

// el: the button element
function AddtoCart(el) {
    // this is the id:
    var id = el.id;

    // and this is an example data attribute. You can have as many as you wish:
    var foo = el.dataset.foo;
    alert(id + " (" + foo + ") added!");
}

// Try add a div or something around the area where all the buttons
// will be placed. Even those that will be added dynamically.
// This optimizes it a lib, as every click inside that div will trigger
// onButtonClick()
document.getElementById("buttons").addEventListener("click", onButtonClick);

// this shows that even works when you dynamically add a button later
document.getElementById('add').onclick = addButton;
function addButton() {
    var s = document.createElement("span");
    s.text = "Add to cart";
    var b = document.createElement("button");
    b.innerHTML = 'Third <span class="addtocartbutton">Add to cart</span>';
    b.className = "addtocart";
    b.id="third";
    b.dataset.foo="trio";
    // note the new button has the same html structure, class
    // and it's added under #buttons div!
    document.getElementById("buttons").appendChild(b);
}


// this will gett triggered on every click on #buttons
function onButtonClick(event) {
    var el = event.target;
    if (el && el.parentNode && el.parentNode.classList.contains('addtocart')) {
      // call your original handler and pass the button that has the
      // id and the other datasets
      AddtoCart(el.parentNode);
    }
}
<div id="buttons">
  <button class="addtocart" id="first" data-foo="uno">First <span class="addtocartbutton">Add to cart</span></button>
  <button class="addtocart" id="second" data-foo="duo">Second <span class="addtocartbutton">Add to cart</span></button>
</div>


<button id="add">Add new button</button>

【讨论】:

  • document.getElementsByClassName("addtocart") 返回一个类似数组的结构,称为NodeList,而不是数组。 IIRC 它是一个 live NodeList 甚至更陌生。
  • 谢谢,@JeremyJStarcher,修复了 NodeList
【解决方案2】:

虽然给出的答案是正确的,但还有另一种方法:Event Delegation

将侦听器附加到单个事物,在本例中为文档body,然后检查实际点击了哪个元素:

警告:动态输入:未经测试

// Only needed *once* and items may be added or removed on the fly without
// having to add/remove event listeners.
document.body.addEventListener("click", addtoCart);

function addtoCart(event) {
    var target = event.target;

    while(target) {
      if (target.classList.contains('addtocart')) {
        break;
      }
      // Note: May want parentElement here instead.
      target = target.parentNode;
    }

    if (!target) {
       return;
    }

    var id = target.dataset.id;
    alert(id + " added!");
}

【讨论】:

  • 这看起来很有希望。要是我能理解就好了! :-) 例如,你为什么需要while?以及为什么没有事件的目标(参考:if (!target))。为什么不用“这个”?
  • 阅读我在帖子中包含的链接,但简短的回答:因为this 不会指向您期望的元素。 IIRC,它指向您实际单击的元素,它可能是 inside 您实际检查的元素。我现在无法对其进行测试,但您可以添加console.log 并观察this 的值是什么。我承认,委派有点难以理解,但如果您正在对内容进行任何类型的动态更新,它比添加/删除特定的处理程序要好得多。
  • 如果您点击页面上的任意位置,则会出错
  • 它适用于删除数据集,因此 var id = target.id;。当我在 Firebug 中监视目标时,它显示 id 而不是 dataset 作为子表达式。
  • 我看不到您的代码...让您很难做任何购买猜测,但这可能会对您有所帮助:stackoverflow.com/questions/20522887/…
【解决方案3】:

您应该将click 事件附加到类addtocart 的每个元素上,因为getElementsByClassName() 返回具有给定类名的所有对象的数组,因此您可以使用for 循环遍历它们并将其与您想在点击时触发的功能(在我的示例中,此功能称为 my_function),请查看以下示例:

var class_names= document.getElementsByClassName("addtocart");

for (var i = 0; i < class_names.length; i++) {
    class_names[i].addEventListener('click', my_function, false);
}

希望这会有所帮助。


function my_function() {
     alert(this.id);
};

var class_names= document.getElementsByClassName("addtocart");

for (var i = 0; i < class_names.length; i++) {
    class_names[i].addEventListener('click', my_function, false);
}
<button class="addtocart" id="id_1">button 1</button>
<button class="addtocart" id="id_2">button 2</button>
<button class="addtocart" id="id_3">button 3</button>
<button class="addtocart" id="id_3">button 4</button>

【讨论】:

  • 我看到一个与此类似的答案,但问题是 ids 是在事后生成的,即页面加载时。所以,我不能真正提前将一个函数与每个函数关联起来。
  • 是的,我明白了,这就是为什么我在答案中使用class 名称来关联点击事件,所以如果类名存在则自动生成 ID 并不重要。
  • 我喜欢你的解决方案,但我觉得它与下面的其他答案有一个根本性的缺陷。我真的认为每次有人单击一个项目以将其添加到购物车时,让它循环遍历数组中的所有项目是低效的代码。想象一下显示数百个项目的情况 - 每次点击都会产生大量开销!我宁愿回到指向按钮的 onclick html 中的函数的旧且被认为是糟糕的方式。如
  • 通常你应该只在第一次循环,之后每次添加新元素时都可以直接将事件附加到它,无论如何做你认为是真的,祝你好运,编码愉快。跨度>
【解决方案4】:

实际上 Javascript 中的类是用于多选的,您应该像数组一样提供索引。

 <button class="addtocart"> <span id="addtocartbutton">Add to cart</span></button>
        <script type="text/javascript">
        document.getElementsByClassName("addtocart")[0].addEventListener("click", AddtoCart);        
        function AddtoCart() {
            alert("Added!");
        }
        </script>

另外你的第二个参数是错误的,不要使用括号。

加括号表示加载后会自动调用函数,加载后不再调用函数。

【讨论】:

  • 使用括号不是wrong。这意味着该函数将内联执行。您需要知道何时使用它们以及何时不使用它们。有些用例需要内联调用。 :)
  • @AdityaParab 是的,你是对的,应用括号并没有错,但这是错误的,因为我认为在单击添加到购物车后不会自动将产品添加到购物车中。虽然我已经更新了我的 ans 并添加了更多关于括号的信息。
【解决方案5】:
<html>
<head>
<script>
window.onload=function{
    var btn = document.getElementsByName("addtocartbtn")[0];
    btn.addEventListener("click", AddtoCart());
}

function AddtoCart() {
    alert("Added!");
}
</script>
</head>
<body >
<button class="addtocart" name ="addtocartbtn" id="<?php echo $code; ?>" > <span id="addtocartbutton">Add to cart</span></button>

</body>
</html>

【讨论】:

  • 这不是只做第一项吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 2017-09-06
  • 2014-05-19
相关资源
最近更新 更多