我想改变$.prepend()
(可能还有$.append()
)的功能,以便进行“on DOM change event”。
我可以做一些简单的事情:
$.prepend = function() { alert('Hello World'); };
或者我是否需要使用$.extend()
功能或$.prototype.prepend
或$.fn.prepend
?
[我意识到我需要在我的新函数中包含prepend()
函数的原始源代码,否则jQuery会破坏!]
编辑::最终解决方案
对于那些感兴趣的人:
$.extend($, {
domChangeStack: [],
onDomChange: function(selector, fn, unbind, removeFromStack) {
/* Needs to store: selector, function, unbind flag, removeFromStack flag */
jQuery.domChangeStack.push([selector, fn, unbind, removeFromStack]);
},
domChangeEvent: function() {
/* Ideally should only affect inserted HTML/altered DOM, but this doesn't */
var stackItem, newStack = [];
while (stackItem = jQuery.domChangeStack.pop()) {
var selector = stackItem[0],
fn = stackItem[1],
unbind = stackItem[2],
remove = stackItem[3];
if (unbind) { $(selector).unbind(); }
// Need to pass the jQuery object as fn is anonymous
fn($(selector));
if (!remove) { newStack.push(stackItem); }
}
jQuery.domChangeStack = newStack;
// Show something happened!
console.log("domChangeEvent: stack size = " + newStack.length);
}
});
$.fn.prepend = function() {
var result = this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
// Need to actually alter DOM above before calling the DOMChange event
$.domChangeEvent();
return result;
};
用法:
/* Run the given function on the elements found by the selector,
* don't run unbind() beforehand and don't pop this DOMChange
* event off the stack.
*/
$.onDomChange(".element_class", function(jObj) {
jObj.do_something_awesome();
}, false, false);
答案 0 :(得分:3)
您要使用哪种方法取决于您需要更改多少。由于.prepend
只是一种驻留在.fn
中的方法,因此您不必混淆原型。
在大多数情况下,它足以重命名原始方法,创建自己的功能,完成所需的操作并以调用原始函数结束,如下所示:
var orgPrepend = $.fn.prepend;
$.fn.prepend = function(){
// Do what you want here
// Call org prepend and return
return orgPrepend.apply(this, arguments);
}
注意:.apply
和.call
或多或少相同。唯一的区别是,.apply
通过引用传递参数,而.call
按值传递参数,因此我倾向于尽可能在.apply
之前使用.call
。 See MDC for reference
但是如果你看一下jQuery的来源(参见src/manipulation.js),你会发现这个方法非常小,所以你可以直接实现它。
在下一个示例中,我将使用.extend
代替,但这不是必须的;你可以像第一个例子中那样替换它。
$.extend($.fn, {
prepend: function() {
// Do what you want here
console.log("prepend was called");
// Execute domManip
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
}
});
您可以以相同的方式覆盖.domManip
或任何其他方法,如下例所示。你可能会在这里看到我更喜欢使用.extend
的原因。
var _domManip = $.fn.domManip;
$.extend($.fn, {
domManip: function() {
// Do what you want here
console.log("domManip was called");
_domManip.apply(this, arguments);
},
prepend: function() {
// Do what you want here
console.log("prepend was called");
// Execute domManip
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.insertBefore( elem, this.firstChild );
}
});
}
});
答案 1 :(得分:2)
我做了一点测试,看来你必须更换$.fn.prepend
。无论如何,如果你想要你可以做类似的事情:
var old=$.fn.prepend;
$.fn.prepend=function(){
//Trigger DOMchange event
old.apply(this, arguments);
};
通过这种方式,您可以将旧的prepend函数包装在一个新函数中,而无需重写函数代码。