繁体   English   中英

jQuery 单击/在两个函数之间切换

[英]jQuery click / toggle between two functions

我正在寻找一种方法,可以在单击某些内容时运行两个独立的操作/功能/“代码块”,然后在再次单击同一内容时运行一个完全不同的代码块。 我把这个放在一起。 我想知道是否有更有效/更优雅的方式。 我知道 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);
    }
});

jQuery 有两个称为.toggle()的方法。 另一个[docs]完全符合您对点击事件的要求。

注意:似乎至少从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 上找到

演示

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

带有操作代码的演示

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

微型 jQuery 插件

如果你想要你自己的可链接的clickToggle jQuery 方法,你可以这样做:

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

如果你想要它更短(为什么要一个,对吧?! )你可以使用Bitwise XOR *Docs运算符,如:
演示

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

就这样。
诀窍是为this对象设置一个boolean属性tog ,并使用否定tog = !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
演示

$("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中,然后在数组的末尾,您只需根据从传递给函数的tog属性分别执行函数 [ 0 // 1 ] this参考:

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

我会为你展示的代码做这样的事情,如果你需要做的只是切换一个值:

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

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

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

我认为您不应该实现 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();
    }
}

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

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

编辑:
jQuery 有一个switchClass方法,当与 hasClass 结合使用时,可用于在您定义的两个宽度之间设置动画。 这是有利的,因为您可以稍后在样式表中更改这些大小或添加其他参数,如背景颜色或边距,以进行过渡。

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

 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

(请注意,第二个不在我的脑海中,我混合了很多语言,所以不能保证确切的语法。应该接近真正的 Javascript。)

修改第一个答案,您可以在 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>

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM