11

関数の 1 つを置き換えることによって、jQuery UI オブジェクトの機能の一部を微調整したい場合、どうすればそれを実行できますか?

例: jQuery オートコンプリート ウィジェットが提案をレンダリングする方法を変更したいとします。次のようなオートコンプリート オブジェクトのメソッドがあります。

_renderItem: function( ul, item) {
    return $( "<li></li>" )
        .data( "item.autocomplete", item )
        .append( "<a>" + item.label + "</a>" )
        .appendTo( ul );
},

これを交換できますか?

これはMonkey Patchingと呼ばれるかもしれません。

どのように?どの構文を使用しますか?

4

2 に答える 2

19

jQuery UI についてはわかりませんが、一般的には次のように関数を再定義します。

(function() {
   var _oldFunc = _renderItem;

   _renderItem = function(ul,item) {
      // do your thing
      // and optionally call the original function:
      return _oldFunc(ul,item);
   }
})();

これが匿名関数でラップされている理由は、元の関数を格納するためのクロージャを作成するためです。このようにして、グローバル変数に干渉することはありません。


編集
jQuery UI ウィジェットの fn に対してこれを行うには、次の構文を使用します。

参考までに、関数を取得する方法は次のとおりです。

function monkeyPatchAutocomplete() { 

  // don't really need this, but in case I did, I could store it and chain 
  var oldFn = $.ui.autocomplete.prototype._renderItem; 

  $.ui.autocomplete.prototype._renderItem = function( ul, item) { 
     // whatever
  }; 
} 
于 2010-03-12T22:31:03.210 に答える
1

古い質問であることはわかっていますが、古いプロジェクトのバグを修正する必要があり、この種のパッチに問題がありました。

options オブジェクトを介して関数を使用できるようにしてから、特定のロジックをそこに配置することをお勧めします。

パッチ:

(function monkeyPatchJQueryAutocomplete($) {

  /**
   * Proxies a private
   * prototype method to the
   * options Object
   *
   * @param  {Object} obj
   * @param  {String} funcName
   */
  function proxyPrivateMethodToOptions(obj, funcName) {
    var __super = obj.prototype[funcName];
    obj.prototype[funcName] = function() {
      if (this.options[funcName]) {
        return this.options[funcName].apply(this, arguments);
      }
      return __super.apply(this, arguments);
    };
  }

  // Make the private _renderItem
  // method available through the options Object
  proxyPrivateMethodToOptions($.ui.autocomplete, '_renderItem');

  // We can do this for other methods as well:
  proxyPrivateMethodToOptions($.ui.autocomplete, '_renderMenu');

}($));

使用例:

$('.some-input').autocomplete({
  _renderItem: function(ul, item) {
    console.log('here we can reference the old func via: ', __super);
    return $("<li>")
      .append($("<a>").text(item.label))
      .appendTo(ul);
  }
});
于 2015-01-16T08:59:42.260 に答える