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

时间:2021-10-01 23:52:21

I would just like to know whats the best of these 3 approaches, and perhaps why?

我想知道这三种方法中最好的是什么,为什么?

1)

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)

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)

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 个解决方案

#1


7  

2) is the correct answers.

2)是正确答案。

For 1) there is no reason to create a new instance of the two functions for each .pluginName call since they are static.

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

For 3) I consider it bad practice to make those local .pluginName call specific variables static to your plugin. It may not cause an error right now but it's likely to induce subtle bugs.

对于3)我认为让那些本地的。pluginname调用特定的变量到你的插件中是不好的做法。它现在可能不会导致错误,但很可能会引起细微的错误。

Basically everything inside the init function should be specific to the call where as everything inside your (function($) { closure should be static to your plugin.

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

Have you tried 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);

As a general comment having an API of $(obj).pluginName("method", ...) can be annoying/unintuitive as an API design.

作为一个具有$(obj) API的通用注释。作为一个API设计,pluginName(“方法”,…)可能会令人讨厌/不直观。

I would recommend allow you to $(obj).pluginName().method(...) aswell to keep the jQuery chaining thing going.

我建议您使用$(obj). pluginname ().method(…)来保持jQuery链接。

#1


7  

2) is the correct answers.

2)是正确答案。

For 1) there is no reason to create a new instance of the two functions for each .pluginName call since they are static.

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

For 3) I consider it bad practice to make those local .pluginName call specific variables static to your plugin. It may not cause an error right now but it's likely to induce subtle bugs.

对于3)我认为让那些本地的。pluginname调用特定的变量到你的插件中是不好的做法。它现在可能不会导致错误,但很可能会引起细微的错误。

Basically everything inside the init function should be specific to the call where as everything inside your (function($) { closure should be static to your plugin.

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

Have you tried 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);

As a general comment having an API of $(obj).pluginName("method", ...) can be annoying/unintuitive as an API design.

作为一个具有$(obj) API的通用注释。作为一个API设计,pluginName(“方法”,…)可能会令人讨厌/不直观。

I would recommend allow you to $(obj).pluginName().method(...) aswell to keep the jQuery chaining thing going.

我建议您使用$(obj). pluginname ().method(…)来保持jQuery链接。