什么是最优雅的方式来创建一个jQuery插件?

时间:2011-02-28 16:14:19

标签: jquery jquery-plugins

我想知道这3种方法中最好的方法,也许为什么?

1)

(function($) {
    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    var $el         = $(this),

                    /* some variables */
                        $selector1  = $el.find('container'),
                        count       = $selector1.length,
                        $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    doSomething1();
                    doSomething2();

                    function doSomething1() {
                        $selector1.css('width' , '300px');
                    };

                    function doSomething2() {
                        $selector2.each(function(i) {
                            //do something
                        });
                    };  
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        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.pluginName' );
        }
    };
})(jQuery);

2)

(function($) {
    var internal= {
        doSomething1    : function($selector1) {
            $selector1.css('width' , '300px');
        },
        doSomething1    : function($selector2) {
            $selector2.each(function(i) {
                //do something
            });
        }
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    /* 
                    The variables are declared here
                    other methods are declared in the internal obj literal
                    */
                    var $el         = $(this),

                    /* some variables */
                        $selector1  = $el.find('container'),
                        count       = $selector1.length,
                        $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    internal.doSomething1($selector1);
                    internal.doSomething2($selector2);
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        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.pluginName' );
        }
    };
})(jQuery);

3)

(function($) {
    /* 
    The variables are declared here
    */
    var $el,
        $selector1,
        count,
        $selector2;

    var internal= {
        doSomething1    : function() {
            $selector1.css('width' , '300px');
        },
        doSomething1    : function() {
            $selector2.each(function(i) {
                //do something
            });
        }
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    /* 
                    The variables are set here
                    other methods are declared in the internal obj literal
                    */
                    $el         = $(this),
                    $selector1  = $el.find('container'),
                    count       = $selector1.length,
                    $selector2  = $el.find('pictures');

                    /* do something e.g.*/
                    internal.doSomething1();
                    internal.doSomething2();
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        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.pluginName' );
        }
    };
})(jQuery);

1 个答案:

答案 0 :(得分:7)

2)是正确答案。

对于1),没有理由为每个.pluginName调用创建两个函数的新实例,因为它们是静态的。

对于3)我认为将这些本地.pluginName调用特定变量静态地插入到插件中是不好的做法。它现在可能不会导致错误,但它可能会导致细微的错误。

基本上init函数中的所有内容都应该特定于调用,因为(function($) {闭包内的所有内容都应该对您的插件是静态的。

你试过4)吗?

(function($) {
    var MyObject = function($el) {
        /* 
        The variables are declared here
        other methods are declared in the internal obj literal
        */
        /* some variables */
        this.$selector1  = $el.find('container');
        var count       = $selector1.length;
        this.$selector2  = $el.find('pictures');

        /* do something e.g.*/
        this.doSomething1($selector1);
        this.doSomething2($selector2);
    };

    MyObject.prototype.doSomething1 = function() {
       this.$selector1.css('width' , '300px');
    };
    MyObject.prototype.doSomething2 = function() {
       this.$selector2.each(function(i) {
           //do something
       });
    };

    var methods = {
        init    : function(options) {
            if( this.length ){
                var settings = {
                    something   : 'fast'
                };
                return this.each(function(){
                    if ( options ) {
                        $.extend( settings, options );
                    }

                    new MyObject($(this));
                });
            }
        },
        update  : function() { },
        destroy : function() { }
    };

    $.fn.pluginName = function(method) {
        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.pluginName' );
        }
    };
})(jQuery);

作为API设计的API $(obj).pluginName("method", ...)的一般性评论可能令人讨厌/不直观。

我建议您允许$(obj).pluginName().method(...)以及保持jQuery链接。