在Javascript中切换点击处理程序

时间:2013-01-03 08:21:33

标签: javascript jquery events click handler

我有一个HTML按钮,我使用jQuery的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);
}

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

通过在每个处理程序中调用e.stopPropagation()可以很容易地解决这个问题,但这会产生消极的副作用,即取消可能已独立附加的任何其他点击处理程序。

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

6 个答案:

答案 0 :(得分:8)

  

更新:由于此版本的toggle()已在jQuery 1.9中删除,因此以下解决方案不再有效。请参阅this question   的替代品。

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

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

上面的代码会注册myFirstHandlerFunctionmySecondHandlerFunction,以便通过备用点击进行调用。

答案 1 :(得分: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`
}

答案 2 :(得分:1)

这个解决方案是一个黑客,但它 简短而且很适合你的粗糙工作:

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

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

请注意,三元操作的第一部分使用=而不是=====,即它是一项任务,而非比较。另请注意,第一次单击按钮时,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>

答案 3 :(得分: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)

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

答案 4 :(得分:-1)

这有助于在按钮上添加数据点击状态属性

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

});

});

答案 5 :(得分:-2)

像这样:

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

handler = 0;

function myMasterHandler(e) {
    if(handler == 0) {
        myFirstHandler(e);
        handler = 1;
    } else {
        mySecondHandler(e);
        handler = 0;
    }
}