Мне нравится архитектура плагина jQuery, однако меня расстраивает (вероятно, из-за непонимания с моей стороны), когда я хочу сохранить ссылку на экземпляр плагина для доступа к свойствам или методам позже в моем коде.

Изменить: я хочу уточнить, что я действительно пытаюсь сохранить ссылку на методы и свойства, используемые в плагине, чтобы я мог использовать их позже

Возьмем, к примеру, значок загрузки AJAX. В более традиционной среде ООП я мог:

var myIcon = new AJAXIcon();
myIcon.start();
//some stuff
myIcon.stop();

Методы и свойства моего объекта хранятся в переменной для дальнейшего использования. Теперь, если я хочу иметь такую ​​же функциональность в плагине jQuery, я бы назвал его из своего основного кода примерно так:

$("#myId").ajaxIcon()

По соглашению мой плагин должен возвращать исходный объект jQuery, переданный моему плагину, с учетом цепочки, но если я это сделаю, я потеряю возможность доступа к методам и свойствам экземпляра плагина.

Теперь я знаю, что вы можете объявить публичную функцию в моем плагине, что-то вроде

$.fn.ajaxIcon = function(options) {
    return this.each(function () {
        //do some stuff
    }
}

$.fn.ajaxIcon.stop = function() {
    //stop stuff
}

Однако, не нарушая соглашения о возврате исходного объекта jQuery, я не могу сохранить ссылку на конкретный экземпляр плагина, на который я хочу сослаться.

Я бы хотел сделать что-то вроде этого:

var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon 
myIcon.start();
//some stuff
myIcon.stop();

Любые мысли?

33
Daniel 23 Июн 2009 в 22:29

5 ответов

Лучший ответ

Если вы сделаете что-то вроде следующего:

(function($){

$.fn.myPlugin = function(options) {
    // support multiple elements
    if (this.length > 1){
        this.each(function() { $(this).myPlugin(options) });
        return this;
    }

    // private variables
    var pOne = '';
    var pTwo = '';
    // ...

    // private methods
    var foo = function() {
        // do something ...
    }
    // ...

    // public methods        
    this.initialize = function() {
        // do something ...
        return this;
    };

    this.bar = function() {
        // do something ...
    };
    return this.initialize();
}
})(jQuery);

Затем вы можете получить доступ к любому из ваших общедоступных методов:

var myPlugin = $('#id').myPlugin();

myPlugin.bar();

Это взято из этой очень полезная статья (май 2009 г.) с сайта trueevil.com, который сам по себе является расширением эта статья (октябрь 2007 г.) с сайта learningjquery.com.

92
wolfyuk 17 Июн 2013 в 12:23

Хорошо, я понял, как это сделать:

Код плагина:

$.ajaxIcon.init = function(element, options) {
    //your initialization code

    this.start = function() {
         //start code
    }

    this.stop = function() {
         //stop code
    }
}

$.fn.ajaxIcon = function(options) {
    this.each(function () {
        //This is where the magic happens
        jQuery(this).data('ajaxIcon', new jQuery.ajaxIcon.init(this, opts));
    });

return this;
}

Затем, чтобы использовать его где-нибудь еще в вашем коде:

var myIcon = $("#myId").ajaxIcon.data('ajaxIcon') 
// myIcon: a reference to the 'init' object specific to this plugin instance
myIcon.start();
myIcon.stop();

Вуаля, ответил на свой вопрос :)

3
Daniel 23 Июн 2009 в 19:33

Я думаю, вы могли бы достичь того, что ищете, с помощью чего-то вроде этого:

var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon 
$.ajaxIcon.start(myIcon);//some stuff
$.ajaxIcon.stop(myIcon);

Однако не тестировал - у меня нет доступа к среде, в которой я могу сделать этот банкомат

0
Josh E 23 Июн 2009 в 19:07

Пример плагина со всеми функциями:

    <script type="text/javascript">
(function( $ ) {

    $.fn.PluginX = function( options ) {
        // Default variables
        // var defaults = {textColor: "#000", backgroundColor: "#fff"}
        // var opts = $.extend( {}, defaults, options );

        // Or
        var settings = $.extend( {}, $.fn.PluginX.defaults, options );

        // Private function
        var privFunc = function(txt) {
            return "Private function " + txt;
        };

        // Public function
        this.pubFunc = function(txt) {
            console.log("\r\nPublic function " + txt);
            return this;
        };

        // Public function2
        this.pubFunc2 = function(txt) {
            console.log("\r\nPublic function " + txt);

            // Private from public
            privFunc("\r\nPrivate function from public -- " + txt);
            return this;
        };

        // Our plugin implementation code goes here.
        return this.each(function() {
            // alert(opts.validate);
            $(this).on('click',function(){
                var elem = $( this );
                var markup = elem.text();                                
                console.log("\r\nElement text " + markup);

                // Function private
                console.log(privFunc(markup));

                // External func
                console.log($.fn.PluginX.format(markup));

                // External function
                console.log(external(markup));
            });

            return this;
        });
    };

    // Variable
    $.fn.PluginX.defaults = {
        validate: "username"
    };

    // External Function
    $.fn.PluginX.format = function(txt) {
        return "<strong>" + txt + "</strong>";
    };

    // External Function
    function external(txt){
        return "External " + txt;
    }

})(jQuery);

$(document).ready(function() {
    var pl = $('.txt').PluginX({validate: "words"}).pubFunc("Hello Public").pubFunc2("Hello Public2");        
});
</script>
<p class="txt">Hello Max</p>
<p class="txt">Hello Pax</p>
0
Jony 26 Июл 2019 в 16:16

Большинство плагинов jQuery, которые, как я вижу, пытаются достичь, будут использовать анонимную область видимости и замыкания для ссылки на функции и переменные, уникальные для этого экземпляра. Например, по следующему шаблону:

;(function ($) {
    // your code
})(jQuery);

Между началом и концом модуля вы можете объявить любые функции, которые захотите. Вы не загрязните глобальное пространство имен и сможете сохранить доступ к локальным переменным через закрытие, что может решить многие ваши проблемы. Также не бойтесь использовать функции $.data.

-1
Andrew Noyes 23 Июн 2009 в 18:37