简体   繁体   English

在javascript中,我如何包装一个onclick回调?

[英]In javascript, how can I wrapper an onclick callback?

I want to decorate or wrapper a specific onclick callback such that my code is executed after the original installed callback is called. 我想装饰或包装一个特定的onclick回调,以便在调用原始安装的回调后执行我的代码。

I started with this in order to do it in a semi-python'ic way using function generator with closure: 我开始这样做是为了使用带有闭包的函数发生器以半python的方式进行:

var original_onclick = node.onclick;
function wrapper_onclick() {
    original_onclick.apply(this,arguments);
    my_code();
}
node.onclick = wrapper_onclick;

However, when I use the above code, the original callbacks aren't working properly. 但是,当我使用上面的代码时,原始回调不能正常工作。 Am I passing in the wrong first parameter (context parameter?) this . 我是在传递错误的第一个参数(context参数?) this Do I need to tweak the arguments? 我需要调整参数吗? Is this already in list arguments ? this已经在列表arguments吗?

This is exactly why lots of people worked to find a proper solution for cross browser event listening. 这正是为什么很多人都在寻找适合跨浏览器事件监听的解决方案的原因。 Some browsers don't fire the function in the right context, some browsers don't pass the event argument and so on. 某些浏览器未在正确的上下文中触发该函数,某些浏览器未传递事件参数,依此类推。 It's a lot easier to use a framework, but if you insist on using no frameworks... 使用框架要容易得多,但如果你坚持不使用框架......

First if you have really horrible code like: 首先,如果你有如下可怕的代码:

<a href="javascript:someFunction( this , evaledVariable );otherFn( ohDearVariable )">

Then sorry, no one can help you. 对不起,没有人可以帮到你。

Otherwise... 除此以外...

In any case, you can't attach events directly to a node by simply setting the .onclick attribute and expect it to behave equally cross browser or even work properly in the browser you're developing with. 无论如何,您不能仅通过设置.onclick属性并将其期望在整个浏览器中表现相同,甚至不能在您正在使用的浏览器中正常工作,将事件直接附加到节点。 You must use both addEventListener and attachEvent methods. 您必须同时使用addEventListenerattachEvent方法。

The most simplest way of forking for cross browser events is: 跨浏览器事件的最简单分叉方式是:

var addListener = function( node , event , listener ) {

    if ( node.addEventListener ) {

        node.addEventListener( event , listener , false );

    } else if (node.attachEvent ) {

        node.attachEvent( "on" + event , listener );

    }

}

Same for removing listeners: 删除侦听器也是如此:

var removeListener = function( node , event , listener ) {

    if ( node.addEventListener ) {

        node.removeEventListener( event , listener , false );

    } else if (node.attachEvent ) {

        node.detachEvent( "on" + event , listener );

    }

}

And use it thus: 并使用它:

var nodeListener = function( e ) {
    alert(e.target);
    // run once for demo
    removeListener( node , "click" , nodeListener );
}
// notice we omit the "on" part.
addListener( node , "click" , nodeListener );

So if you want to wrap listeners appended to node the WRONG onclick way: 因此,如果您想将追加到节点的侦听器包装为WRONG onclick方式:

var wrongOnClick = node.onclick;

var listener = function( e ) {
    before();
    wrongOnClick.call( this , e );
    after();
};

addListener( node , "click" , listener );

This will serve most modern browsers including IE, though actually a lot more optimalisation and memory leak prevention code is needed for a good implementation, but instead of writing this code yourself or having others do it for you, use a framework/tookit! 这将适用于包括IE在内的大多数现代浏览器,但实际上需要更多的优化和内存泄漏防护代码才能实现良好的实现,但是不要自己编写这些代码或让其他人为您执行此操作,请使用framework / tookit! Because by the time you have a good implementation running that works cross browser, you will have more code bloat then when you actually used a framework... 因为当你有一个良好的实现运行时,跨浏览器工作,当你实际使用框架时,你会有更多的代码膨胀...

** Addendum ** **附录**

As a hack, I still suggest to use the addEventListener method and keep references to your listeners. 作为一种技巧,我仍然建议使用addEventListener方法并保留对您的侦听器的引用。

var aListener = function( e ) { }
node.addEventListener( "click" , aListener , false );

var wrappedListener = function ( e ) {
   before( e );
   aListener( e );
   after( e );
}
node.removeEventListener( "click" , aListener , false );
node.addEventListener( "click" , wrappedListener , false );

This obviously only works with your listeners, if you want it to wrap existing listeners in a page (listeners from others), then there's simply no way of knowing how people appended their listeners to nodes. 显然,这仅适用于您的侦听器,如果您希望将现有的侦听器包装在页面中(来自其他侦听器的侦听器),则根本无法知道人们如何将侦听器附加到节点上。 If they used addEventListener/attachEvent libraries or the dirty example in the beginning of this post, you simply cannot reliably wrap them without manual coding and looking up the references or manually exposing them. 如果他们在本文开头使用了addEventListener / attachEvent库或肮脏的示例,那么您将无法可靠地包装它们,而无需手动编码,查找引用或手动公开它们。

Based on help from Matt and BGerrissen, the following code works great for chrome: 在Matt和BGerrissen的帮助下,以下代码非常适合chrome:

var original_onclick = node.onclick;
function wrapper_onclick(e ) {
  var ret = original_onclick(e);
  remove_story_onclicks();
  return ret;
}
node.onclick = wrapper_onclick;

Still not exactly sure how to do a bulletproof wrapper like the following in python: 仍然不确定如何在Python中执行防弹包装,如下所示:

def wrappee(foo,bar,baz):
   print foo,bar,baz

def wrapper(*args,**kwargs):
    print 'before'
    wrappee(*args,**kwargs)
    print 'after'

wrapper('a','b','c')

which prints 打印

before
a b c
after

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

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