【问题标题】:attaching a class to a jQuery object将类附加到 jQuery 对象
【发布时间】:2011-09-12 13:39:50
【问题描述】:

我正在为如何最好地结合 javascript 类和 jQuery 插件而苦苦挣扎。这个问题不是很具体,我希望的是指向更多资源的指针。

基本上,我想将状态数据和私有方法存储在一个类中,然后扩展我调用插件的每个 jQuery 对象以具有这些私有方法和属性。这样我就可以在插件内部直接调用 jQuery 对象的方法。

我阅读了jQuery plugin design pattern (common practice?) for dealing with private functions,特别是大卫的回答,但是这每次都会初始化一个新的类,因此不能用于保存对象的状态。

我还找到了http://fuelyourcoding.com/jquery-plugin-design-patterns-part-i/,它建议创建一个类,然后将其存储在 .data() 中。

我认为理想情况下我想要的代码看起来像

(function( $ ){

  var methods = {
    init : function( options ) { // Initialize each object with a state and private methods },
    show : function( ) { 
      // testFoo() is a private method that checks the element's state
      if(this.testFoo()){
        // Relying on jQuery's html() method
        this.html() = this.fooTemplate();
      }
    }
  };

  // Boiler plate plugin from http://docs.jquery.com/Plugins/Authoring
  $.fn.myPlugin = function( method ) {
    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.myPlugin' );
    }    
  };
})( jQuery );

最后,我似乎无法将私有方法直接烘焙到插件中,因为像“testFoo()”这样的方法将返回一个布尔值,因此不可链接。

想法?我以正确的方式接近这个吗?我应该使用另一种设计模式吗?也许根本不使用 jQuery 插件架构?

【问题讨论】:

  • +1 有趣的问题...您基本上希望能够做到 $('div').myPlugin(methods.show); ?并扩展那些特定的 jQuery 对象......所以你可以做 $('div').show()?我接近了吗?

标签: javascript jquery jquery-plugins


【解决方案1】:

这是一个建议的解决方案。它结合了几种不同的方法(John Resig 的继承模型和 Alex Saxton 的插件继承模型)。

定义您的可继承插件:

(function ($) {

    My.Plugin = Class.extend({

        /*
        * Initialization (constructor)
        */
        init: function (element, meta) {
            var $meta = $.extend({ name: "pluginName" }, meta);

            // Call the base constructor
            this._super(element, $meta);

            // TODO: Add custom initialization code like the following:
            // this._testButton = $('.testButton', element).get(0);
        },


        /*
        * Public methods
        */

        show: function() {
             alert('This is a public method');

        },


        /*
        * Private methods
        */

        // DEMO: Overriding the base _paint method:
        _paint: function () {

            // "this._super()" is available in all overridden methods
            // and refers to the base method.
            this._super();

            alert('TODO: implement myPlugin._paint!');
        }


    });


    // Declare this class as a jQuery plugin
    $.plugin('my_plugin', My.Plugin);


})(jQuery);

定义基类

(function () {
    var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/;
    // The base Class implementation (does nothing)
    this.Class = function () { };

    // Create a new Class that inherits from this class
    Class.extend = function (prop) {
        var _super = this.prototype;

        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        initializing = true;
        var prototype = new this();
        initializing = false;


        // Copy the properties over onto the new prototype
        for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] =
                   typeof prop[name] == "function"
                && typeof _super[name] == "function"
                && fnTest.test(prop[name])
                    ? (function (name, fn) {
                        return function () {
                            var tmp = this._super;

                            // Add a new ._super() method that is the same method
                            // but on the super-class
                            this._super = _super[name];

                            // The method only need to be bound temporarily, so we
                            // remove it when we're done executing
                            var ret = fn.apply(this, arguments);
                            this._super = tmp;

                            return ret;
                        };
                    })(name, prop[name])
                    : prop[name];
        }

        // The dummy class constructor
        function Class() {
            // All construction is actually done in the init method
            if (!initializing && this.init)
                this.init.apply(this, arguments);
        }

        // Populate our constructed prototype object
        Class.prototype = prototype;

        // Enforce the constructor to be what we expect
        Class.constructor = Class;

        // And make this class extendable
        Class.extend = arguments.callee;

        return Class;
    };
})();

插件创建

(function ($) {

    //  The "inheritance plugin" model
    //  [http://alexsexton.com/?p=51][1]

    $.plugin = function (name, object) {
        $.fn[name] = function (options) {
            var instance = $.data(this, name, new object(this, options));
            return instance;
        };
    };
})(jQuery);

从 javascript 调用你的插件:

$('#someElem').my_plugin({options: {}, data: {} /* you can modify your plugin code to accept anything */}).show();

注意:

这里的私有方法被标记为_methodName。这是纯粹的约定。如果你真的想隐藏它们,你可以使用模块模式(谷歌或者这里是一个初学者:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

这是你要找的吗?

【讨论】:

  • Mrchief 的解决方案几乎就是我最终使用的解决方案(并且没有遇到太多障碍)。虽然我使用的代码最终来自stackoverflow.com/questions/5980194/…。接受 Mrchief 因为它是一个正确的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2012-02-25
  • 2015-11-14
  • 1970-01-01
  • 1970-01-01
  • 2013-05-17
相关资源
最近更新 更多