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

Ove*_*ack 4 html javascript jquery

首先,我是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;
  })
});
Run Code Online (Sandbox Code Playgroud)
.newclass {
  color: red;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 10

click事件从被单击的元素冒泡到文档,在途中传递所有元素.

那么当你点击你的按钮时会发生什么呢?当类被添加时(因为按钮有类button),点击气泡到form(没有)然后到body(不是)然后到html(这不会"T).您的处理程序在每个级别都被调用,因为您已将它附加到所有元素,因此最后一个(html)获胜.

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

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

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

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

  if (ret) {
    $(".button").addClass("newclass");
  } else {
    $(".button").removeClass("newclass");
  }
});
Run Code Online (Sandbox Code Playgroud)

例:

$(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;
  })
});
Run Code Online (Sandbox Code Playgroud)
.newclass {
  color: red;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

但是,我会完全改变你的方法.我不会在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");
  }
});
Run Code Online (Sandbox Code Playgroud)

等待点击向上冒泡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;
  })
});
Run Code Online (Sandbox Code Playgroud)
.newclass {
  color: red;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

如果您使用的元素可能包含子元素(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...
Run Code Online (Sandbox Code Playgroud)

(我们依赖的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;
  })
});
Run Code Online (Sandbox Code Playgroud)
.newclass {
  color: red;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)