在javascript中用另一个覆盖(包装)现有的jQuery click事件

时间:2016-01-19 17:01:52

标签: javascript jquery

假设我有一个现有按钮,并通过jQuery附加一个单击:

var $button = $('#test').click(function () { console.log('original function') });

现在,假设我要覆盖该单击,以便我可以在该函数之前和之后添加一些逻辑。我已尝试使用以下函数进行绑定和包装。

Function.prototype.bind = function () {
   var fn = this;
   var args = Array.prototype.slice.call(arguments);
   var object = args.shift();

   return function () {
       return fn.apply(object, args.concat(Array.prototype.slice.call(arguments)));
   }
}

function wrap(object, method, wrapper) {
   var fn = object[method];

   return object[method] = function() {
       return wrapper.apply(this, [fn.bind(this)].concat(
        Array.prototype.slice.call(arguments)));
   }
}

所以我用对象的方法调用wrap,该方法是我想要执行的方法和匿名函数的属性。我想:

wrap($button 'click', function (click) {
     console.log('do stuff before original function');
     click();
     console.log('do stuff after original function');
 });

这只调用原始函数。在成功之前,我已经在对象的方法上使用了这种方法。类似于:See this Plunker

任何人都可以帮我解决这个具体的例子吗?

由于

2 个答案:

答案 0 :(得分:3)

您可以创建一个jQuery函数,从数据中获取原始事件处理函数,删除click事件,然后添加一个新的事件处理程序。该函数将具有前后处理程序的两个参数(每个函数)。

$(function() {

    jQuery.fn.wrapClick = function(before, after) {
        // Get and store the original click handler.
        // TODO: add a conditional to check if click event exists.
        var _orgClick = $._data(this[0], 'events').click[0].handler,
            _self = this;

        // Remove click event from object.
        _self.off('click');

        // Add new click event with before and after functions.
        return _self.click(function() {
            before.call(_self);
            _orgClick.call(_self);
            after.call(_self);
        });
    };

    var $btn = $('.btn').click(function() {
        console.log('original click');
    });

    $btn.wrapClick(function() {
        console.log('before click');
    }, function() {
        console.log('after click');
    });

});

Here is a Codepen

答案 1 :(得分:1)

经过长时间的搜索,我得到了与@Corey相同的答案,这是考虑多个事件的类似方式:



function wrap(object, method, wrapper) {
          
  var arr = []
  var events = $._data(object[0], 'events')
  
  if(events[method] && events[method].length > 0){ // add all functions to array
    events[method].forEach(function(obj){
      arr.push(obj.handler)
    })
  }
  
  
  
  if(arr.length){
      function processAll(){ // process all original functions in the right order
        arr.forEach(function(func){
          func.call(object)
        })
      }
  
      object.off(method).on(method, function(e){wrapper.call(object,processAll)}) //unregister previous events and call new method passing old methods
  }
   
    
}


$(function(){
  $('#test').click(function () { console.log('original function 1') });
  var $button = $('#test').click(function () { console.log('original function 2') });
  wrap($button, 'click', function (click,e) {
     console.log('do stuff before original functions');
     click()
     console.log('do stuff after original functions');
 });
})

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>


<div id='test'>click me</div>
&#13;
&#13;
&#13;