在 Javascript 中切换点击处理程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14135264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 20:48:16  来源:igfitidea点击:

Toggling click handlers in Javascript

javascriptjqueryeventsclickhandler

提问by Nathan Friend

I have an HTML button to which I attach an event, using jQuery's bind(), like so:

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

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

In myFirstHandlerFunction, I'd like this handler to replace itself with a new handler, mySecondHandlerFunction, like this:

在 中myFirstHandlerFunction,我希望这个处理程序用一个新的处理程序替换自己mySecondHandlerFunction,如下所示:

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

In the second click handler, mySecondHandlerFunction, I'd like to toggle the button back to its original state: unbind the mySecondHandlerFunctionhandler and reattach the original handler, myFirstHandlerFunction, like so:

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

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

This works great, except for one small detail: because the click event has not yet propagated through each of the button's click handlers, the click event is passed on to the button's next click handler, which happens to be the handler that was just bound in the previous handler. The end result is mySecondHandlerFunctionbeing executed immediately after myFirstHandlerFunctionis executed.

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

This problem can be easily solved by calling e.stopPropagation()in each handler, but this has the negative side-effect of cancelling any other click handlers that may have been attached independently.

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

Is there a way to safely and and consistently toggle between two click handlers, without having to stop the propagation of the click event?

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

回答by Frédéric Hamidi

Update:Since this form of toggle()was removed in jQuery 1.9, the solution below does not work anymore. See this questionfor alternatives.

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

It looks like toggle()would solve your problem:

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

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

The code above will register myFirstHandlerFunctionand mySecondHandlerFunctionto be called on alternate clicks.

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

回答by Cerbrus

Just use a boolean to toggle the functionality of the handler, there's no need to juggle which handler is listening:

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

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

回答by Andrew Willems

This solution is a hack, but it isshort and sweet for your rough work:

这个解决方案是一个 hack,但它对于你粗暴的工作来说短暂而甜蜜的:

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

It's a hack because it's putting a new property directly onto thiswhich is the click-target HTML DOM element, and that's maybe not best practice. However, it thus avoids creates any new globals, and it can be used unchanged on different buttons simultaneously.

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

Note that the first part of the ternary operation uses =and not ==or ===, i.e. it's an assignment, not a comparison. Note also that the first time the button is clicked, this.firstClkis undefined but is immediately negated, making the first part of the ternary operation evaluate to truethe first time.

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

Here's a working version:

这是一个工作版本:

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

回答by BBQ Singular

I was looking at this today, and realized there was still not a way to do this without a global variable listed. I came up with the following to add locations to an ESRI basemap, but it would work generally too:

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

This should allow you to put something else in the section where you overwrite the click handler and not necessitate a global variable.

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

回答by Mike Tavish

This would help add data-click-stateattribute on your button

这将有助于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();
        }
    });
});

回答by ATOzTOA

Like this:

像这样:

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

handler = 0;

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