Какой самый элегантный способ создать плагин jQuery? - PullRequest
5 голосов
/ 28 февраля 2011

Я просто хотел бы знать, что является лучшим из этих трех подходов и, возможно, почему?

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 Ответ

7 голосов
/ 28 февраля 2011

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 $(obj).pluginName("method", ...), он может быть раздражающим / не интуитивным как дизайн API.

Я бы порекомендовал вам позволить $(obj).pluginName().method(...), чтобы поддерживать цепочку jQuery.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...