最佳扩展jQuery插件的方法

78

我是一个相对较新的jQuery用户,想要扩展一个已有的jQuery插件,但该插件只满足了我需求的75%。我已经尽力做好了功课,查看了stackoverflow上的以下问题:

我已经阅读了关于extend方法的介绍。然而,所有这些功课都让我感到困惑。我正在使用fullcalendar插件,并需要修改一些行为以及添加新的事件钩子。我是否被迫在插件闭包内部执行此操作?我是否遗漏了明显的东西?

理想情况下,我们应该能够将我们的代码与插件代码分开,以便进行可能的升级。任何帮助都将不胜感激,特别是指出我缺少哪些信息或对其他Stack Overflow问题中已经提出的解决方案是否合理的意见。对我来说,它们彼此矛盾,我仍然感到困惑。


justkt,你能否发布一些你如何扩展fullcalendar插件的示例代码吗?我目前正在尝试做同样的事情,但是遇到了困难,无法调用我所添加的任何函数。 - Matt McCormick
@MattMcCormick - 你尝试过下面列出的被接受的答案了吗? - justkt
啊,我之前包含了 .prototype。其实不需要的。现在只需要 $.extend(true, $.fullCalendar, extensionMethods); 就可以了!理想情况下,我想扩展 Event 对象,但是它没有命名空间,所以我不知道怎么可能。不过现在这个方法已经可以用了。 - Matt McCormick
2
请参阅http://msdn.microsoft.com/en-us/library/hh404085.aspx(继承章节)。 - katrin
7个回答

86

我刚刚遇到了尝试扩展jQuery UI插件的相同问题,这是我找到的解决方案(通过jquery.ui.widget.js找到):

(function($) {
/**
 * Namespace: 插件所在的命名空间
 * pluginName: 插件的名称
 */
    var extensionMethods = {
        /*
         * 检索元素的id
         * 这是现有插件内的一些上下文
         */
        showId: function(){
            return this.element[0].id;
        }
    };
$.extend(true, $[ 命名空间 ][ 插件名称 ].prototype, extensionMethods);
})(jQuery);

希望这可以帮助您,如果您有任何问题,请随时问我。


2
那么,为了澄清一下,如果我想要扩展jQuery UI的自动完成功能,那么Namespace将是"ui",而pluginName将是"autocomplete",对吗? - Matt Huggins
1
我想我自己回答了这个问题。我在自动完成源代码中找到了它调用 jQuery.widget("ui.autocomplete", ...) 的地方,在小部件源代码中,它在“.”处分割,命名空间为索引0,插件名称为索引1。换句话说,看起来我是正确的。 :) - Matt Huggins
4
@Jared - 我最终采纳了你的建议,扩展了jQuery UI自动完成功能。我在这里描述了我的目标:http://www.matthuggins.com/articles/extending-jquery-uis-autocomplete-to-improve-success,并且我在这里提供了完整的代码:https://github.com/mhuggins/jquery-ui-autocomplete-hints。如果你有任何改进建议,我很乐意听取! - Matt Huggins
4
如何查找命名空间(Namespace)和插件名称(pluginName)? - Pablo S G Pacheco

18

我遇到了同样的问题,来到这里后,Jared Scott 的回答给了我灵感。

(function($) {

    var fullCalendarOrg = $.fn.fullCalendar;

    $.fn.fullCalendar = function(options) {
        if(typeof options === "object") {
            options = $.extend(true, options, {
                // locale
                isRTL: false,
                firstDay: 1,
                // some more options
            });
        }

        var args = Array.prototype.slice.call(arguments,0);
        return fullCalendarOrg.apply(this, args);
    }

})(jQuery);

3
$.fn.APluginName=function(param1,param2)
{
  return this.each(function()
    {
      //access element like 
      // var elm=$(this);
    });
}

// sample plugin
$.fn.DoubleWidth=function()
  {
    return this.each(function()
      {
        var _doublWidth=$(this).width() * 2;
        $(this).width(_doubleWidth);
      });
  }

//

<div style="width:200px" id='div!'>some text</div>

// 使用自定义插件

$('#div1').DoubleWidth();

上述类型的工具通常用于操作DOM元素。

自定义工具

(function($){
  var _someLocalVar;
  $.Afunction=function(param1,param2) {
    // do something
  }
})(jquery);

// 作为访问上述实用程序的方法

$.Afunction();

//这种类型的工具通常是扩展JavaScript


1
这不是他在问什么 - 他在问如何最好地扩展已经存在的插件,以一种允许更新基础插件的同时在其上添加所需功能的方式。 - prodigitalson

3
我发现很多插件的方法都是受保护/私有的(即在闭包作用域中)。如果你需要修改这些方法/函数的功能,除非你愿意分叉它,否则你就没办法了。但如果你不需要改变这些方法/函数中的任何一个,那么你可以使用$.extend($.fn.pluginName, {/*your methods/properties*/};
我以前做过的另一件事是简单地将插件作为我的插件属性来使用,而不是试图扩展它。
总之,一切归结于你想要扩展的插件是如何编码的。

在主扩展中,我想要做的一切都在那里了,但在某些情况下,例如在插件内创建的DOM元素上添加事件处理程序。在其他情况下,我需要覆盖现有方法内部的行为。我读得越多,就越看不到一个清晰的解决方案。还有其他想法吗? - justkt
如果这些方法是公共API中的方法(看起来不是),那么您可以使用我上面提到的方法来替换函数定义。除此之外,没有更好的方法了。您只能将其分叉以供自己使用并进行修改。 - prodigitalson
2
@prodigitalson 公共* API ;) - Niks

1

类似于Jared Scott答案的示例,但是复制原始对象的原型可以调用父方法:

(function($) {

    var original = $.extend(true, {}, $.cg.combogrid.prototype);

    var extension = {
        _renderHeader: function(ul, colModel) {
            original._renderHeader.apply(this, arguments);

            //do something else here...
        }
    };

    $.extend(true, $.cg.combogrid.prototype, extension);

})(jQuery);

1

我在重写jQuery插件时的方法是将需要访问的方法和变量移动到选项块中,并调用“扩展”函数。

// in the plugin js file
$.jCal = function (target, opt) {
    opt = $.extend({
       someFunctionWeWantToExpose: function() {
           // 'this' refers to 'opt', which is where are our required members can be found
       }
    }

    // do all sorts of things here to initialize

    return opt; // the plugin initialisation returns an extended options object
}


////// elsewhere /////

var calendar = $("#cal1").jCal();
calendar.someFunctionWeWantToExpose();

0

jQuery小部件可以使用jQuery小部件工厂进行扩展。

(function ($) {
    "use strict";

    define([
        "jquery",
        "widget"
    ], function ($, widget) {
        $.widget("custom.yourWidget", $.fn.fullCalendar, {
            yourFunction: function () {
                // your code here
            }
        });

        return $.custom.yourWidget;
    });
}(jQuery));

查看jQuery文档以了解更多信息:
Widget Factory API
使用Widget Factory扩展小部件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接