替代支持 eventData 的 jQuery .toggle() 方法?

IT技术 javascript jquery event-handling jquery-events
2021-01-28 10:38:35

jQuery文档.toggle()方法规定:

为方便起见,提供了 .toggle() 方法。手动实现相同的行为相对简单,如果 .toggle() 中内置的假设证明是有限的,那么这可能是必要的。

内置的假设.toggle已经证明对我当前的任务有限制,但文档没有详细说明如何实现相同的行为。我需要传递eventData给提供给 的处理程序函数toggle(),但似乎只.bind()支持这个,而不支持.toggle().

我的第一个倾向是使用一个对单个处理程序函数全局的标志来存储单击状态。换句话说,而不是:

$('a').toggle(function() {
  alert('odd number of clicks');
}, function() {
  alert('even number of clicks');
});

做这个:

var clicks = true;
$('a').click(function() {
  if (clicks) {
    alert('odd number of clicks');
    clicks = false;
  } else {
    alert('even number of clicks');
    clicks = true;
  }
});

我没有测试后者,但我怀疑它会起作用。这是做这样的事情的最佳方式,还是我缺少的更好的方式?

2个回答

似乎是一种合理的方法……我只是建议您使用 jQuery 的数据存储实用程序,而不是引入额外的变量(如果您想跟踪一大堆链接,这可能会让人头疼) . 所以基于你的例子:

$('a').click(function() {
  var clicks = $(this).data('clicks');
  if (clicks) {
    alert('odd number of clicks');
  } else {
    alert('even number of clicks');
  }
  $(this).data("clicks", !clicks);
});
好吧,我尝试在第一次点击时实现 slideDown。还将“a”选择更改为类选择。不确定这是否相关。我在这里复制了这个问题:jsfiddle.net/3gpfc
2021-03-18 10:38:35
@Gnuey - 第一次点击时对我有用(只需将这个确切的源复制/粘贴到我的 Firebug 控制台中,现在这个页面上的每个链接都会首先触发警报)。您是否看到错误,或者只是没有警报?
2021-04-09 10:38:35
@Gnuey - 切换你的slideUpslideDowns。在第一次单击时,clicks将被undefined解释为false,因此它将执行else分支。
2021-04-11 10:38:35
啊,我明白了。我终于明白你的代码了,它很漂亮。谢谢,如果我还没有,我会再次投票!
2021-04-11 10:38:35
谢谢,Alconja - 很好的答案!我很欣赏简洁的代码示例。
2021-04-12 10:38:35

这是一个实现替代 的插件.toggle(),特别是因为它已在 jQuery 1.9+ 中删除。

如何使用:

此方法的签名是:

.cycle( functions [, callback] [, eventType])
  • functions [Array]:要循环的函数数组
  • callback[Function]:每次迭代完成时将执行的函数。它将传递当前迭代和当前函数的输出。可用于处理functions数组中每个函数的返回值
  • eventType [String]:指定要循环的事件类型的字符串,例如。 "click mouseover"

使用示例是:

$('a').cycle([
    function() {
      alert('odd number of clicks');
    }, function() {
      alert('even number of clicks');
    }
]);

我在这里包含了一个演示

插件代码:

(function ($) {
    if (!Array.prototype.reduce) {
        Array.prototype.reduce = function reduce(accumulator) {
            if (this === null || this === undefined) throw new TypeError("Object is null or undefined");
            var i = 0,
                l = this.length >> 0,
                curr;

            if (typeof accumulator !== "function") // ES5 : "If IsCallable(callbackfn) is false, throw a TypeError exception."
            throw new TypeError("First argument is not callable");

            if (arguments.length < 2) {
                if (l === 0) throw new TypeError("Array length is 0 and no second argument");
                curr = this[0];
                i = 1; // start accumulating at the second element
            } else curr = arguments[1];

            while (i < l) {
                if (i in this) curr = accumulator.call(undefined, curr, this[i], i, this);
                ++i;
            }

            return curr;
        };
    }
    $.fn.cycle = function () {
        var args = Array.prototype.slice.call(arguments).reduce(function (p, c, i, a) {
            if (i == 0) {
                p.functions = c;
            } else if (typeof c == "function") {
                p.callback = c;
            } else if (typeof c == "string") {
                p.events = c;
            }
            return p;
        }, {});
        args.events = args.events || "click";
        console.log(args);
        if (args.functions) {
            var currIndex = 0;

            function toggler(e) {
                e.preventDefault();
                var evaluation = args.functions[(currIndex++) % args.functions.length].apply(this);
                if (args.callback) {
                    callback(currIndex, evaluation);
                }
                return evaluation;
            }
            return this.on(args.events, toggler);
        } else {
            //throw "Improper arguments to method \"alternate\"; no array provided";
        }
    };
})(jQuery);