jQuery单击/在两个功能之间切换


72

我正在寻找一种方法,当单击某些内容时,可以运行两个单独的操作/函数/“代码块”,然后在再次单击同一内容时,运行一个完全不同的块。我把这个放在一起。我想知道是否有更有效/更优雅的方法。我知道jQuery .toggle(),但有点烂。

在这里工作:http//jsfiddle.net/reggi/FcvaD/1/

var count = 0;
$("#time").click(function() {
    count++;
    //even odd click detect 
    var isEven = function(someNumber) {
        return (someNumber % 2 === 0) ? true : false;
    };
    // on odd clicks do this
    if (isEven(count) === false) {
        $(this).animate({
            width: "260px"
        }, 1500);
    }
    // on even clicks do this
    else if (isEven(count) === true) {
        $(this).animate({
            width: "30px"
        }, 1500);
    }
});

14
toggle()不吮吸,它只是不做您需要的事情;)
Felix Kling


1
这段代码有很大帮助。谢谢!
nholloway4'7

Answers:


70

jQuery有两个称为的方法.toggle()。在另一个[文件]不正是你想要的click事件。

注意:似乎至少从jQuery 1.7开始,此版本.toggle弃用,可能正是出于这个原因,即存在两个版本。利用.toggle改变元素的知名度仅仅是一个更常见的用法。该方法已在jQuery 1.9删除

下面是一个示例,说明了如何实现与插件相同的功能(但可能会暴露与内置版本相同的问题(请参见文档的最后一段))。


(function($) {
    $.fn.clickToggle = function(func1, func2) {
        var funcs = [func1, func2];
        this.data('toggleclicked', 0);
        this.click(function() {
            var data = $(this).data();
            var tc = data.toggleclicked;
            $.proxy(funcs[tc], this)();
            data.toggleclicked = (tc + 1) % 2;
        });
        return this;
    };
}(jQuery));

演示

(免责声明:我不是说这是最好的实现!我敢打赌,可以在性能方面进行改进)

然后调用:

$('#test').clickToggle(function() {   
    $(this).animate({
        width: "260px"
    }, 1500);
},
function() {
    $(this).animate({
        width: "30px"
    }, 1500);
});

更新2:

同时,我为此创建了一个合适的插件。它接受任意数量的功能,并可用于任何事件。可以在GitHub上找到


@ThomasReggi:谢谢您的更新。我写这本书已经很晚了;)但是,没有必要使用this.each,特别是因为这将为funcs每个元素创建一个数组和新的事件处理函数。修复并添加了演示。
菲利克斯·克林

我不明白...为什么不只使用api.jquery.com/toggle-event?您甚至在答案中提到了它……也许您应该突出显示该部分,因为它是本机jQuery方法。
dmmd 2012年

@jlcd:这就是为什么我将其放在答案的开头。我修改了答案以强调更多,您认为现在更好吗?TBH,我写了代码,后来发现了另.toggle一种方法。我不想扔掉那个代码……
Felix Kling 2012年


1
@Syed:当然,只需将data.toggleclicked元素设置为要重置为的索引即可。
菲利克斯·克林

66

演示

.one()文档。

我回答得很晚,但是我认为这是最短的代码,可能会有所帮助。

function handler1() {
    alert('First handler: ' + $(this).text());
    $(this).one("click", handler2);
}
function handler2() {
    alert('Second handler: ' + $(this).text());
    $(this).one("click", handler1);
}
$("div").one("click", handler1);

使用Op的代码进行演示

function handler1() {
    $(this).animate({
        width: "260px"
    }, 1500);
    $(this).one("click", handler2);
}

function handler2() {
    $(this).animate({
        width: "30px"
    }, 1500);
    $(this).one("click", handler1);
}
$("#time").one("click", handler1);

@urjitonrails很高兴能为您提供帮助:)
Tushar Gupta-curioustushar 2014年

1
如此巧妙的解决方案。队友的欢呼声!
卡尔·帕普沃思

2
到目前为止,这是完美的!
埃克斯坦(Eckstein)

惊人的解决方案!!!从来都不知道该.one()方法,但是它非常有用。感谢
Si8 20年

49

微型jQuery插件

如果您想要自己的可链接的clickToggle jQuery Method,可以这样做:

jQuery.fn.clickToggle = function(a, b) {
  return this.on("click", function(ev) { [b, a][this.$_io ^= 1].call(this, ev) })
};

// TEST:
$('button').clickToggle(function(ev) {
  $(this).text("B"); 
}, function(ev) {
  $(this).text("A");
});
<button>A</button>
<button>A</button>
<button>A</button>

<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>


简单功能切换器

现场演示

function a(){ console.log('a'); }
function b(){ console.log('b'); }

$("selector").click(function() { 
  return (this.tog = !this.tog) ? a() : b();
});

如果您希望它更短(为什么要这样,对吗?!),则可以使用按位异或 * Docs运算符,例如:
DEMO

  return (this.tog^=1) ? a() : b();

就这样。
诀窍是为thisObject设置一个boolean属性tog,然后使用negationtog = !tog)对其进行切换
,并将所需的函数调用放入条件运算符中 ?:




在OP的示例中(甚至包含多个元素)可能看起来像:

function a(el){ $(el).animate({width: 260}, 1500); }
function b(el){ $(el).animate({width: 30}, 1500);  }

$("selector").click(function() {
  var el = this;
  return (el.t = !el.t) ? a(el) : b(el);
}); 

你也可以存储-toggle,如:
DEMO

$("selector").click(function() {
  $(this).animate({width: (this.tog ^= 1) ? 260 : 30 });
}); 

但这不是OP的确切要求,因为他是 looking for a way to have two separate operations / functions


使用Array.prototype.reverse

注意:这不会存储当前的Toggle状态,而只会反转我们在Array中的函数位置(它有它的用途...)

您只需将a,b函数存储在数组中,单击即可简单地反转数组顺序并执行array[1]函数:

现场演示

function a(){ console.log("a"); }
function b(){ console.log("b"); }
var ab = [a,b];

$("selector").click(function(){
  ab.reverse()[1](); // Reverse and Execute! // >> "a","b","a","b"...
});

一些混搭!

jQuery演示
JavaScript演示

创建一个toggleAB()包含两个函数的漂亮函数,将它们放在Array中,并在数组的末尾0 // 1分别根据togthis 引用传递给函数的属性分别执行函数[ ] :

function toggleAB(){
  var el = this; // `this` is the "button" Element Obj reference`
  return [
    function() { console.log("b"); },
    function() { console.log("a"); }
  ][el.tog^=1]();
}

$("selector").click( toggleAB );

2
很棒的答案!谢谢
亚历克斯·霍尔斯格罗夫

我大部分都了解。但是我不知道“ tog”来自哪里?el.tog ^ = 1如何在0和1之间交替显示?感谢thnx
koz

@koz.tog只是我们添加到this对象中的属性。就像您说“Person.name = "koz"人是一个对象”一样,您要分配一个name属性而不是一个值。有关XOR运算符的更多信息,请参见^stackoverflow.com/a/22061240/383904(您可以在我的答案中找到相同的链接;))
Roko C. Buljan

@ RokoC.Buljan thnx的回应,非常感谢。我看了一下链接,但没有解释我喜欢理解的数学原理。我知道它返回0、1、0、1 ...但是它是如何做到的?实际上,“ ^ = 1”在数学上实际上意味着等于0、1、0、1的含义。thnx
koz

@koz认为二进制,零和一。XOR运算符在每个操作数(而不是两个操作数)的对应位所在的每个位位置返回a 。oneones现在,正如您所注意到的,我们始终会反对ones(1运算符:operand^1所以这是一个结果表0^1 =11^1 =0。到目前为止一切顺利-结果正在改变!但是要真正修改我们的运算符,el.tog您需要使用Assignment运算符(= -然后就可以了!el.tog^=1。现在回到小表,您将了解现在为el.tog属性分配了哪些值。
Roko C. Buljan

24

如果您需要做的就是切换一个值,那么我会对显示的代码执行类似的操作:

var oddClick = true;
$("#time").click(function() {
    $(this).animate({
        width: oddClick ? 260 : 30
    },1500);
    oddClick = !oddClick;
});

这仅适用于唯一元素。我建议删除oddClick-part,然后将width:-line替换为width: $(this).width() == 30 ? 260 : 30
mgutt

15

我用它来创建两个函数之间的切换效果。

var x = false;
$(element).on('click', function(){
 if (!x){
  //function
  x = true;
 }
 else {
  //function
  x = false;
 }
});

谢谢:)非常有用!
Emil Gurbanov

5

我不认为您应该实现toggle方法,因为将其从jQuery 1.9中删除是有原因的。

考虑使用jQuery完全支持的toggleClass:

function a(){...}
function b(){...}   

例如,假设您的事件触发器是onclick,因此:

第一种选择:

$('#test').on('click', function (event) {

    $(this).toggleClass('toggled');

    if ($(this).hasClass('toggled')) {
        a();
    } else{
        b();
    }
}

您还可以将处理程序函数作为参数发送:

第二种选择:

$('#test').on('click',{handler1: a, handler2: b}, function (event) {

    $(this).toggleClass('toggled');

    if ($(this).hasClass('toggled')) {
        event.data.handler1();
    } else{
        event.data.handler2();
    }
}

1

如果您所做的只是保持布尔值,isEven则可以考虑检查isEven元素上是否有类,然后切换该类。

使用像count这样的共享变量是一种不好的做法。问问自己,该变量的作用范围是什么,想一想您是否要在页面上切换10个项目,是否要创建10个变量,或者创建一个数组或变量来存储它们的状态?可能不会。

编辑:
jQuery有一个switchClass方法,当它与hasClass结合使用时,可以在您定义的两个宽度之间进行动画处理。这是有利的,因为您可以稍后在样式表中更改这些大小,或添加其他参数(例如background-color或margin)进行过渡。


1

使用几个函数和一个布尔值。这是一个模式,不是完整的代码:

 var state = false,
     oddONes = function () {...},
     evenOnes = function() {...};

 $("#time").click(function(){
     if(!state){
        evenOnes();
     } else {
        oddOnes();
     }
     state = !state;
  });

要么

  var cases[] = {
      function evenOnes(){...},  // these could even be anonymous functions
      function oddOnes(){...}    // function(){...}
  };

  var idx = 0; // should always be 0 or 1

  $("#time").click(function(idx){cases[idx = ((idx+1)%2)]()}); // corrected

(请注意,第二个是我的脑袋,我混合了很多语言,因此不能保证确切的语法。应该接近真实的Java语言。)


除了语法错误,第二个也不起作用。您$("#time").click(..)仅调用一次即可设置要调用的函数。
Felix Kling

只需要另一个匿名函数来调用正确的大小写即可。
zzzzBov 2011年

0

修改第一个答案,您可以在n个功能之间切换:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus.com®">
<!-- <script src="../js/jquery.js"></script> -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
  <title>my stupid example</title>

 </head>
 <body>
 <nav>
 <div>b<sub>1</sub></div>
<div>b<sub>2</sub></div>
<div>b<sub>3</sub></div>
<!-- .......... -->
<div>b<sub>n</sub></div>
</nav>
<script type="text/javascript">
<!--
$(document).ready(function() {
	(function($) {
        $.fn.clickToggle = function() {
          var ta=arguments;
	        this.data('toggleclicked', 0);
          this.click(function() {
				    id= $(this).index();console.log( id );
            var data = $(this).data();
            var tc = data.toggleclicked;
            $.proxy(ta[id], this)();
            data.toggleclicked = id
          });
          return this;
        };
   }(jQuery));

    
	$('nav div').clickToggle(
	    function() {alert('First handler');}, 
        function() {alert('Second handler');},
        function() {alert('Third handler');}
		//...........how manny parameters you want.....
		,function() {alert('the `n handler');}
	);

});
//-->
</script>
 </body>
</html>


0

一线解决方案: 基本思路:

$('sth').click(function () {
    let COND = $(this).propery == 'cond1' ? 'cond2' : 'cond1';
    doSomeThing(COND);
})

jsfiddle上的示例

示例1,以切换模式更改元素的innerHTML:

$('#clickTest1').click(function () {
    $(this).html($(this).html() == 'click Me' ? 'clicked' : 'click Me');
});

示例2,在“ none”和“ inline-block”之间切换显示:

$('#clickTest2, #clickTest2 > span').click(function () {
    $(this).children().css('display', $(this).children().css('display') == 'inline-block' ? 'none' : 'inline-block');
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.