假设我有一个现有按钮,并通过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
任何人都可以帮我解决这个具体的例子吗?
由于
答案 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');
});
});
答案 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;