39

我正在尝试做一些非常简单的事情。基本上我有一个可点击的 div '热点',当你点击它时,它会填满屏幕并显示一些内容。我通过简单地更改 div 的类、删除“spot”并添加“grown”来实现这一点,并且有一些 CSS 动画可以让它增长。这工作正常。

问题是,在这个 div 中有一个 close_button,目前它只是文本。我希望这可以将课程切换回来-即删除已增长和已阅读的点。单击时它不会执行此操作。我相信这与 DOM 加载时没有这些类的元素有关,但我是 jQuery 新手,不知道如何解决这个问题。

我认为可能有一种更明智的方法,有人可以指出我正确的方向吗?我将不胜感激。我尝试使用 toggleClass 来代替,但无济于事。

$( document ).ready(function() {      
    $(".clickable").click(function() {  
        $(this).addClass("grown");  
        $(this).removeClass("spot");
    });   

    $(".close_button").click(function() {  
        alert (this);
        $("#spot1").removeClass("grown");  
        $("#spot1").addClass("spot");
    });   
});

更新:

我现在正在使用此代码,

$( document ).ready(function() {   
    $(document).on("click", ".close_button", function () { 
        alert ("oi");
        $("#spot1").addClass("spot");
        $("#spot1").removeClass("grown");
    });  


    $(document).on("click", ".clickable", function () {
        if ($(this).hasClass("spot")){
            $(this).addClass("grown");
            $(this).removeClass("spot");
        }
    });
});

奇怪的是,close_button 函数仍然不会添加“spot”或删除“grown”,尽管它会添加任何其他类并且会删除其他类...我添加了 if 子句,因为我认为这两个函数可能同时被触发时间,互相抵消,但似乎没有区别

4

10 回答 10

80

发生的情况是您的关闭按钮被放置在您的.clickablediv 内,因此单击事件将在两个元素中触发。

事件冒泡将使点击事件从子节点传播到其父节点。所以你的.close_button回调将首先执行,当.clickable到达时,它会再次切换类。由于运行速度非常快,您不会注意到这两个事件发生了。

                    / \
--------------------| |-----------------
| .clickable        | |                |
|   ----------------| |-----------     |
|   | .close_button | |          |     |
|   ------------------------------     |
|             event bubbling           |
----------------------------------------

为了防止您的事件到达.clickable,您需要将事件参数添加到您的回调函数中,然后stopPropagation在其上调用该方法。

$(".close_button").click(function (e) { 
    $("#spot1").addClass("spot");
    $("#spot1").removeClass("grown");
    e.stopPropagation();
});

小提琴:http: //jsfiddle.net/u4GCk/1/

有关一般事件顺序的更多信息:http ://www.quirksmode.org/js/events_order.html (那是我选择漂亮的 ASCII 艺术 =])

于 2013-10-30T21:42:14.697 回答
16

该问题是由于事件冒泡引起的。添加的代码的第一部分.grown工作正常。

单击链接时的第二部分“删除成长的类”不能按预期工作,因为处理程序.close_button.clickable被执行。因此,它删除了grown该类并将其读取到div.

您可以通过使用e.stopPropagation()内部.close_button单击处理程序来避免这种情况,以避免事件冒泡。

演示:http: //jsfiddle.net/vL8DP/

完整代码

$(document).on('click', '.clickable', function () {
   $(this).addClass('grown').removeClass('spot');
}).on('click', '.close_button', function (e) {
   e.stopPropagation();
   $(this).closest('.clickable').removeClass('grown').addClass('spot');
});
于 2013-10-31T16:27:45.607 回答
8

每当我看到addClass并且removeClass我想为什么不直接使用toggleClass. 在这种情况下,我们可以删除.clickable该类以避免事件冒泡,并避免在我们单击.clickable div.

$(document).on("click", ".close_button", function () { 
    $(this).closest(".grown").toggleClass("spot grown clickable");
});  

$(document).on("click", ".clickable", function () {
    $(this).toggleClass("spot grown clickable");
}); 

我还为您推荐一个父包装器,.clickable divs而不是使用document. 我不确定你是如何动态添加它们的,所以不想为你假设你的布局。

http://jsfiddle.net/bplumb/ECQg5/2/

快乐编码:)

于 2013-10-31T16:30:22.793 回答
7

我建议缓存您多次使用的 jQuery 对象。例如:

    $(document).on("click", ".clickable", function () {
        $(this).addClass("grown");
        $(this).removeClass("spot");
    });

将会:

    var doc = $(document);
    doc.on('click', '.clickable', function(){
       var currentClickedObject = $(this);
       currentClickedObject.addClass('grown');
       currentClickedObject.removeClass('spot');
    });

它实际上更多的代码,但它更快,因为您不必“遍历”整个 jQuery 库来获取 $(this) 对象。

于 2013-11-06T10:27:49.987 回答
4

我想你快到了。问题是,您$(this)在“关闭按钮”中的侦听器不是可点击的 div。所以你想先搜索它。尝试替换$(this)$(this).closest(".clickable"). 并且不要忘记e.stopPropagation()Guilherme 的建议。那应该是这样的:

$( document ).ready(function() {   
    $(document).on("click", ".close_button", function () { 
        alert ("oi");
        e.stopPropagation()
        $(this).closest(".clickable").addClass("spot");
        $(this).closest(".clickable").removeClass("grown");
    });  


    $(document).on("click", ".clickable", function () {
        if ($(this).hasClass("spot")){
            $(this).addClass("grown");
            $(this).removeClass("spot");
        }
    });
});
于 2013-11-06T18:34:03.680 回答
1

为什么不简化呢?

jQuery

$('.clickable').on('click', function() {//on parent click
    $(this).removeClass('spot').addClass('grown');//use remove/add Class here because it needs to perform the same action every time, you don't want a toggle
}).children('.close_button').on('click', function(e) {//on close click
    e.stopPropagation();//stops click from triggering on parent
    $(this).parent().toggleClass('spot grown');//since this only appears when .grown is present, toggling will work great instead of add/remove Class and save some space
});

这样维护起来就容易多了。

做了一个小提琴:http: //jsfiddle.net/filever10/3SmaV/

于 2013-11-06T11:41:36.597 回答
1

使用.on()

您需要事件委托,因为当 DOM 准备好时,这些类不存在于 DOM 上。

$(document).on("click", ".clickable", function () {
    $(this).addClass("grown");
    $(this).removeClass("spot");
});
$(document).on("click", ".close_button", function () {  
    $("#spot1").removeClass("grown");
    $("#spot1").addClass("spot");
});  
于 2013-09-24T16:04:56.957 回答
1

尝试这个 :

$('.close-button').on('click', function(){
  $('.element').removeClass('grown');
  $('.element').addClass('spot');
});

$('.element').on('click', function(){
  $(this).removeClass('spot');
  $(this).addClass('grown');
});

我希望我理解你的问题。

于 2013-09-24T16:09:16.967 回答
0

我认为问题在于元素的嵌套。将事件附加到外部元素后,对内部元素的点击实际上会为外部元素触发相同的点击事件。所以,你实际上永远不会进入第二种状态。您可以做的是检查单击的元素。如果是关闭按钮,则避免更改类。这是我的解决方案:

var element = $(".clickable");
var closeButton = element.find(".close_button");
var onElementClick = function(e) {
    if(e.target !== closeButton[0]) {
        element.removeClass("spot").addClass("grown");
        element.off("click");
        closeButton.on("click", onCloseClick);
    }
}
var onCloseClick = function() {
    element.removeClass("grown").addClass("spot");
    closeButton.off("click");
    element.on("click", onElementClick);
}
element.on("click", onElementClick);

此外,我正在添加和删除事件处理程序。

JSFiddle -> http://jsfiddle.net/zmw9E/1/

于 2013-10-30T21:56:45.867 回答
0

实际上,我只是通过交换更改属性的顺序解决了我遇到的问题。例如,我首先更改了属性,但实际上我必须在修改属性之前删除类并添加新类。我不确定它为什么会起作用,但它确实起作用了。所以要尝试的事情是从 更改$("XXXX").attr('something').removeClass( "class" ).addClass( "newClass" )$("XXXX").removeClass( "class" ).addClass( "newClass" ).attr('something')

于 2019-05-16T17:22:47.780 回答