2

「on DOM change event」を実現するために、$.prepend()(そしておそらくの)機能を変更したいと思います。$.append()

次のような簡単なことはできますか?

$.prepend = function() { alert('Hello World'); };

$.extend()または、関数 or$.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);
4

2 に答える 2

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引数を参照で渡し、値で渡すことです。そのため、可能な場合はbefore.callを使用することを好みます。参照用に MDC を参照してください.apply.call

しかし、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 );
            }
        });
    }
});

jsFiddle のテスト ケースを参照してください

于 2011-05-19T09:14:44.390 に答える
2

少しテストしましたが、交換する必要があるようです$.fn.prepend。とにかく、必要に応じて次のようなことができます:

var old=$.fn.prepend;
$.fn.prepend=function(){
   //Trigger DOMchange event
   old.apply(this, arguments);
};

このようにして、関数コードを書き直すことなく、古い prepend 関数を新しい関数でラップできます。

于 2011-05-19T09:14:21.097 に答える