jQuery:不会将类添加到标记或立即删除它

时间:2016-09-01 08:15:30

标签: javascript jquery html

首先,我是jQuery的新手。创建一个简单的程序并不是火箭科学,但以下代码的效果对我来说没有任何意义。我的意图是在点击一个带有“.button”类的元素之后,应该向该元素添加一个新类。否则 - 点击其他地方 - 应该删除当前的新类。不幸的是,即使条件为真,也会执行else中的代码。我的想法存在哪些缺陷?你能解决这个问题吗?

$(function() {
  $("*").click(function() {
    var ret = $(this).hasClass("button");

    if (ret) {
      $(".button").addClass("newclass");
    } else {
      $(".button").removeClass("newclass");
    }
  });

  $("form").on("submit", function() {
    return false;
  })
});
.newclass {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
  <input type="text" name="">
  <input type="submit" name="" class="button">
</form>

2 个答案:

答案 0 :(得分:10)

click个事件冒泡从被点击的元素到文档,传递到途中的所有元素。

那么当您单击按钮时会发生的情况是,在添加类时(因为按钮具有类button),点击会弹到form(没有),然后到body(不是)然后到html(没有)。您的处理程序在每个级别都被调用,因为您已将它附加到所有元素,因此最后一个(html)获胜。

因此,对代码的最小更改是在处理点击时停止传播(告诉事件停止冒泡):

$("*").click(function(e) {
// Note --------------^

  e.stopPropagation(); // <===

  var ret = $(this).hasClass("button");

  if (ret) {
    $(".button").addClass("newclass");
  } else {
    $(".button").removeClass("newclass");
  }
});

示例:

$(function() {
  $("*").click(function(e) {
    e.stopPropagation();
    
    var ret = $(this).hasClass("button");

    if (ret) {
      $(".button").addClass("newclass");
    } else {
      $(".button").removeClass("newclass");
    }
  });

  $("form").on("submit", function() {
    return false;
  })
});
.newclass {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
  <input type="text" name="">
  <input type="submit" name="" class="button">
</form>

但是,我会彻底改变你的做法。我没有在DOM中的每个元素上设置处理程序,而只是附加到document,然后检查e.target

$(document).click(function(e) {
// ^^^^^^ --- note --------^

  var ret = $(e.target).hasClass("button");
// Note ------^^^^^^^^

  if (ret) {
    $(".button").addClass("newclass");
  } else {
    $(".button").removeClass("newclass");
  }
});

等待点击冒泡到document.body,然后查看它从哪里冒出来(e.target)。

示例:

$(function() {
  $(document).click(function(e) {
  // Note ------------------------^

    var ret = $(e.target).hasClass("button");

    if (ret) {
      $(".button").addClass("newclass");
    } else {
      $(".button").removeClass("newclass");
    }
  });

  $("form").on("submit", function() {
    return false;
  })
});
.newclass {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
  <input type="text" name="">
  <input type="submit" name="" class="button">
</form>

如果您使用的元素可能包含子元素(例如button而不是input),那么您可能会遇到点击可能来自孩子的情况或后代。在这种情况下,您可以使用closest来确定点击是否通过.button元素传递到document

var ret = $(e.target).closest(".button").length;
if (ret) {
    // The element clicked or an ancestor of it has the class...

(我们依赖的事实是0是假的,但所有其他非NaN数字都不是。)

示例:

$(function() {
  $(document).click(function(e) {
  // Note ------------------------^

    var ret = $(e.target).closest(".button").length;

    if (ret) {
      $(".button").addClass("newclass");
    } else {
      $(".button").removeClass("newclass");
    }
  });

  $("form").on("submit", function() {
    return false;
  })
});
.newclass {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<form method="get" action="">
  <input type="text" name="">
  <button class="button">
    Direct <strong>Child</strong>
  </button>
</form>

答案 1 :(得分:-1)

首先在表单中添加一个选择器,如下所示:

<form method="get" action="" class="simpleForm">
<input type="text" name="">
<input type="submit" name="" class="button">
</form>

监听任何点击事件的下一个目标,检查点击是否仅在输入上发生。

$('.simpleForm').unbind('click').bind('click', function(e) {
    if($(this).hasClass('button') && e.target.tagName === 'input') {
        $(this).addClass("newclass");
    } else {
        $(this).removeClass("newclass");
    }
});