我正在尝试做一些非常简单的事情。基本上我有一个可点击的div'热点',当你点击它填满屏幕并显示一些内容。我通过简单地改变div的类,删除'spot'并添加'grow'来实现这一点,并且有一些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'或删除'grow'虽然它会添加任何其他类并且它将删除其他类...我添加了if子句因为我认为可能两个函数都被触发同时,相互撤消,但似乎没有区别
答案 0 :(得分:60)
当您的关闭按钮放在.clickable
div中时会发生什么,因此将在两个元素中触发click事件。
事件冒泡将使click事件从子节点传播到其父节点。因此,您的.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艺术=])
答案 1 :(得分:13)
问题是由event bubbling引起的。您添加.grown
的代码的第一部分可以正常工作。
第二部分“删除已成熟的类”在单击链接时无法正常工作,因为.close_button
和.clickable
的处理程序都已执行。因此,它会将grown
类移除并读取到div
。
您可以在e.stopPropagation()
点击处理程序中使用.close_button
来避免此事件,以避免事件冒泡。
DEMO: 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');
});
答案 2 :(得分:7)
每当我看到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/
快乐编码:)
答案 3 :(得分:4)
我建议您多次缓存您使用的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');
});
它实际上更多的代码,但它是muuuuuuch更快,因为你不必“遍历”整个jQuery库,以获得$(this)对象。
答案 4 :(得分:3)
我想你差不多了。
问题是,“关闭按钮”监听器中的$(this)
不是可点击的div。所以你想先搜索它。尝试将$(this)
替换为$(this).closest(".clickable")
。并且不要忘记Guilherme建议的e.stopPropagation()
。应该是这样的:
$( 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");
}
});
});
答案 5 :(得分:1)
试试这个:
$('.close-button').on('click', function(){
$('.element').removeClass('grown');
$('.element').addClass('spot');
});
$('.element').on('click', function(){
$(this).removeClass('spot');
$(this).addClass('grown');
});
我希望我理解你的问题。
答案 6 :(得分: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
});
这样维护起来就容易多了。
答案 7 :(得分:0)
使用.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");
});
答案 8 :(得分: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/
答案 9 :(得分:0)
我实际上通过交换更改属性的顺序解决了我遇到的一个问题。例如,我先更改属性,但实际上我必须先删除该类并添加新类,然后再修改属性。我不确定为什么会奏效,但确实奏效了。因此,可以尝试将$("XXXX").attr('something').removeClass( "class" ).addClass( "newClass" )
更改为$("XXXX").removeClass( "class" ).addClass( "newClass" ).attr('something')
。