我可以替换或修改jQuery UI小部件上的函数吗?怎么样? (猴子补丁)

时间:2010-03-12 22:28:16

标签: jquery monkeypatching

如果我想调整jQuery UI对象的一些功能,通过替换其中一个函数,我将如何去做?

示例:假设我想修改jQuery自动完成小部件呈现建议的方式。自动完成对象上有一个方法如下:

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

我可以替换它吗?

我认为这可能被称为 Monkey Patching

如何?我会使用什么语法?

2 个答案:

答案 0 :(得分:18)

我不了解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
  }; 
} 

答案 1 :(得分:0)

我知道这是一个老问题,但我只需修复一个旧项目的一些错误,并且遇到了这种补丁的问题。

最好通过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);
  }
});