我有一堆元素可以获得三个不同的类:neutral
,markedV
和markedX
。当用户单击其中一个元素时,类会切换一次:中性 - > markedV - > markedX - >中性。每次单击都会切换类并执行一个函数。
$(document).ready(function(){
$(".neutral").click(function markV(event) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
$(this).unbind("click");
$(this).click(markX(event));
});
$(".markedV").click(function markX(event) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
$(this).unbind("click");
$(this).click(neutral(event));
});
$(".markedX").click(function neutral(event) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
$(this).unbind("click");
$(this).click(markV(event));
});
});
但显然这不起作用。我想我有三个障碍:
如何将更改元素正确绑定到已定义的函数,有时在实际定义之前?
如何确保将事件传递给新绑定的函数[我想这不是通过向函数发送'event'来实现的,就像在markX(事件)中一样)
整个事情看起来很重复,唯一改变的是警报行动(尽管每个功能的行为都不同,不一定是警报)。对此有更优雅的解决方案吗?
答案 0 :(得分:1)
不需要经常绑定和取消绑定事件处理程序。
您应该为所有这些选项配备一个处理程序:
$(document).ready(function() {
var classes = ['neutral', 'markedV', 'markedX'],
methods = {
neutral: function (e) { alert('Good!') },
markedV: function (e) { alert('Bad!') },
markedX: function (e) { alert('Ok!') },
};
$( '.' + classes.join(',.') ).click(function (e) {
var $this = $(this);
$.each(classes, function (i, v) {
if ( $this.hasClass(v) ) {
methods[v].call(this, e);
$this.removeClass(v).addClass( classes[i + 1] || classes[0] );
return false;
}
});
});
});
答案 1 :(得分:1)
对于此类情况,您需要将事件附加到更高的父级并委派事件。
请记住,事件附加到元素而不是类。
尝试这种方法
$(document).ready(function () {
$(document).on('click', function (e) {
var $target = e.target;
if ($target.hasClass('markedV')) {
alert("Good!");
$target.addClass("markedV").removeClass("neutral");
} else if ($target.hasClass('markedV')) {
alert("Bad!");
$target.addClass("markedX").removeClass("markedV");
} else if ($target.hasClass('markedX')) {
alert("Ok!");
$target.addClass("neutral").removeClass("markedX");
}
});
});
或为@Bergi建议
$(document).ready(function () {
$(document).on('click', 'markedV',function (e) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
});
$(document).on('click', 'markedX',function (e) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
});
$(document).on('click', 'neutral',function (e) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
});
});
此处文档可以替换为任何静态父容器..
答案 2 :(得分:0)
如何正确地将更改元素绑定到已定义的函数,有时在它实际定义之前?
您不将元素绑定到函数,将处理函数绑定到元素上的事件。您无法在定义函数之前使用该函数(但您可能会使用代码中声明的位置上方的函数 - 称为“吊装”)。
如何确保将事件传递给新绑定的函数[我猜这不是通过向函数发送'event'来实现的,就像在markX(event)中一样)
这就是调用处理程序时隐式发生的事情。您只需要传递函数 - do not call it!但问题是您无法从外部访问命名函数表达式。
整个事情看起来很重复,唯一改变的是警报行动(尽管每个功能都会采取不同的行动,不一定是警报)。对此有更优雅的解决方案吗?
是。仅使用一个处理程序,并动态决定在当前状态下执行的操作。不要稳定地绑定和取消绑定处理程序。或者使用event delegation。