在Javascript中切换点击处理程序

我有一个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()可以很容易地解决此问题,但这具有消除可能已独立附加的任何其他单击处理程序的负面副作用。

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

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

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

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

上面的代码将注册myFirstHandlerFunctionmySecondHandlerFunction ,以便在备用点击时调用。

只需使用布尔值来切换处理程序的function,就不需要处理哪个处理程序正在侦听:

 $('#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` } 

这个解决方案是一个黑客,但它对你的粗糙工作来说简短而且甜蜜:

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

not yet clicked

NOT YET CLICKED

我今天看着这个,并意识到如果没有列出全局变量,仍然没有办法做到这一点。 我想出了以下内容来向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) 

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

这有助于在按钮上添加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(); } }); }); 

像这样:

 $(this).bind('click', myMasterHandler); handler = 0; function myMasterHandler(e) { if(handler == 0) { myFirstHandler(e); handler = 1; } else { mySecondHandler(e); handler = 0; } }