0

我有一堆元素得到三个不同的类neutralmarkedVmarkedX。当用户单击这些元素之一时,类会切换一次:中性 -> 标记V -> 标记X -> 中性。每次点击都会切换类并执行一个功能。

$(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));
  });
});

但显然这行不通。我认为我有三个障碍:

  1. 如何正确地将更改的元素绑定到已经定义的函数,有时在它实际定义之前?

  2. 如何确保将事件传递给新绑定的函数

  3. 整个事情看起来是重复的,唯一改变的是警报动作(虽然每个函数的行为不同,不一定是警报)。有没有更优雅的解决方案?

4

3 回答 3

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;
            }
        });
    });
});

这是小提琴:http: //jsfiddle.net/m3CyX/

于 2013-01-15T03:03:56.980 回答
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");
  });
});

这里的文档可以用任何静态父容器替换..

于 2013-01-15T03:06:06.003 回答
0

如何正确地将更改的元素绑定到已经定义的函数,有时在它实际定义之前?

您不会将元素绑定到函数,而是将处理函数绑定到元素上的事件。您不能在定义之前使用函数(但您可以在代码中声明它的位置上方使用函数- 称为“提升”)。

如何确保将事件传递给新绑定的函数

这就是调用处理程序时隐式发生的事情。你只需要传递函数——不要调用它!然而,您的问题是您无法从外部访问命名函数表达式。

整个事情看起来是重复的,唯一改变的是警报动作(虽然每个函数的行为不同,不一定是警报)。有没有更优雅的解决方案?

是的。仅使用一个处理程序,并动态决定在当前状态下要做什么。不要稳定地绑定和解除绑定处理程序。或者使用事件委托

于 2013-01-15T03:07:03.800 回答