How to set a private variable for a jQuery plugin?

2019-07-11 14:36发布

问题:

I would like to create a simple plugin, which works with the text of the element as a default value, or you can set this value, when you call the plugin.

But if I don't set the value, and call the plugin for more than one element, the default value getting multiplied.

(function($) {
    $.fn.reText = function(options) {
        var settings = $.extend({
            label : $(this).text()
        }, options);
        return this.each(function() {
            $(this).text(settings.label);
        });
    };
})(jQuery);

call:

$(function() {
    $('div').reText();
});

the result:

<div>text 1</div>
<div>text 2</div>

jsFiddle

I know, the problem is the settings's scope, but I don't know how to resolve the problem...

回答1:

Move the settings variable declaration inside of each function, so that it will different for each element / div.

The sample code will be as follows:

 return this.each(function() {
    var settings = $.extend({
      label : $(this).text()
    }, options);

    $(this).text(settings.label);
 });

Updated Fiddle



回答2:

it has to be inside the each loop, so that each element in the given set will gets its own default value

(function ($) {
    $.fn.reText = function (options) {
        return this.each(function () {
            var settings = $.extend({
                label: $(this).text()
            }, options);
            $(this).text(settings.label);
        });
    };
})(jQuery);

Demo: Fiddle



回答3:

In reponse to your further query about how to give other methods access to your private variables, you can simply set a 'self' context at the start of your iteration and then reference that. All other methods declared within your iteration can still reference self.settings, although they themselves will be within a new function context.

$.fn.reText = function(options) {
    return this.each(function() {
        var self = this;

        self.settings = $.extend({
            label : $(this).text()
        }, options);

        $(this).text(self.settings.label);

        self.DoSomething = function() {
            console.log(self.settings.label);
        }
    });
};

Or, if you are outside the scope of your iteration loop, you could set your instance data using the Jquery .data method, given your dependance on jquery.

// Store
$(this).data("reText", self.settings);
...
console.log($(this).data("reText"))

Fiddle