6

我有一个使用 jQuery 附加事件的 HTML 按钮bind(),如下所示:

$('#mybutton').bind('click', myFirstHandlerFunction);

myFirstHandlerFunction中,我希望这个处理程序用一个新的处理程序替换自己mySecondHandlerFunction,就像这样:

function myFirstHandlerFunction(e) {
    $(this).unbind('click', myFirstHandlerFunction).bind('click', mySecondHandlerFunction);
}

在第二个单击处理程序中mySecondHandlerFunction,我想将按钮切换回其原始状态:取消绑定mySecondHandlerFunction处理程序并重新附加原始处理程序,myFirstHandlerFunction如下所示:

function mySecondHandlerFunction(e) {
    $(this).unbind('click', mySecondHandlerFunction).bind('click', myFirstHandlerFunction);
}

这很好用,除了一个小细节:因为点击事件还没有通过按钮的每个点击处理程序传播,所以点击事件被传递到按钮的下一个点击处理程序,它恰好是刚刚绑定的处理程序前一个处理程序。最终结果mySecondHandlerFunction在执行后立即myFirstHandlerFunction执行。

通过调用每个处理程序可以轻松解决此问题e.stopPropagation(),但这具有取消可能已独立附加的任何其他单击处理程序的负面影响。

有没有办法在两个点击处理程序之间安全、一致地切换,而不必停止点击事件的传播?

4

6 回答 6

8

更新:由于在 jQuery 1.9 中删除了这种形式,toggle()下面的解决方案不再起作用。请参阅此问题以获取替代方案。

看起来toggle()可以解决您的问题:

$("#mybutton").toggle(myFirstHandlerFunction, mySecondHandlerFunction);

上面的代码将注册myFirstHandlerFunctionmySecondHandlerFunction在交替点击时被调用。

于 2013-01-03T08:26:02.420 回答
6

只需使用布尔值来切换处理程序的功能,无需调整正在侦听的处理程序:

$('#mybutton').bind('click', myHandlerFunction);
var first = true;

function myHandlerFunction(e) {
    if(first){
        // Code from the first handler here;
    }else{
        // Code from the second handler here;
    }
    first = !first; // Invert `first`
}
于 2013-01-03T08:24:37.693 回答
1

此解决方案是一种 hack,但对于您的粗略工作来说,它又又甜:

$('#myButton').click(function() {
  (this.firstClk = !this.firstClk) ? firstHandler(): secondHandler();
});

这是一个 hack,因为它直接在其上放置了一个新属性this,即点击目标 HTML DOM 元素,这可能不是最佳实践。但是,它因此避免了创建任何新的全局变量,并且可以同时在不同按钮上不加改变地使用它。

请注意,三元运算的第一部分使用=and not ==or ===,即它是一个赋值,而不是一个比较。另请注意,第一次单击按钮时,this.firstClk未定义但立即被否定,使得三元运算的第一部分计算为true第一次。

这是一个工作版本:

$('#a > button').click(function() {(this.firstClk = !this.firstClk) ? a1(): a2();});
$('#b > button').click(function() {(this.firstClk = !this.firstClk) ? b1(): b2();});

function a1() {$('#a > p').text('one');}
function a2() {$('#a > p').text('two');}

function b1() {$('#b > p').text('ONE');}
function b2() {$('#b > p').text('TWO');}
div {display: inline-block;width: 10em;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a"><p>not yet clicked</p><button>click</button></div>
<div id="b"><p>NOT YET CLICKED</p><button>CLICK</button></div>

于 2016-02-18T17:00:26.427 回答
0

我今天正在看这个,并意识到如果没有列出全局变量,仍然没有办法做到这一点。我想出了以下将位置添加到 ESRI 底图的方法,但它通常也可以工作:

function addLocationClickHandler() {
    var addLocationClick = overviewMap.on('click', function (event) {
        addLocationClick.remove();
    })
    $('#locationAddButton').one('click', function (cancelEvent) {
        addLocationClick.remove();
        $('#locationAddButton').on('click', addLocationClickHandler)
    });
}

$('#locationAddButton').on('click', addLocationClickHandler)

这应该允许您在覆盖点击处理程序的部分中放置其他内容,而不需要全局变量。

于 2015-03-10T16:14:05.737 回答
-1

这将有助于data-click-state在您的按钮上添加属性

$(document).ready(function() {
    $('#mybutton').on('click', function() {
        if ($(this).attr('data-click-state') == 1) {
            $(this).attr('data-click-state', 0)
            myFirstHandlerFunction();
        } else {
            $(this).attr('data-click-state', 1)
            mySecondHandlerFunction();
        }
    });
});
于 2016-10-27T18:08:23.840 回答
-2

像这样:

$(this).bind('click', myMasterHandler);

handler = 0;

function myMasterHandler(e) {
    if(handler == 0) {
        myFirstHandler(e);
        handler = 1;
    } else {
        mySecondHandler(e);
        handler = 0;
    }
}
于 2013-01-03T08:25:52.937 回答