如何在jquery插件中使用全局变量多实例化

时间:2015-07-30 08:12:02

标签: jquery jquery-plugins

在我的插件中,我使用全局函数来读取/写入插件的每个部分的值。 如果我只为一个元素使用插件但是如果我将它用于多个元素我有问题(全局变量被覆盖),这可以正常工作。

;(function ($, window, document, undefined) {

    'use strict';

    var globalParams = {},
        opts = {};

    $.fn.myPlugin = function(options) {
        opts = $.extend(true, {}, $.fn.myPlugin.defaults, options);
        return this.each(function() {
            var $this = $(this);
            var that = this;
            var el = $this.attr("id");
            globalParams.name = opts.name;
            globalParams.color = opts.color;
            globalParams.car = opts.car;

            debug.call(that, el);

            $this.on('click', '.btn', function() {
                debug.call(that, el);
            });
        });
    };

    $.fn.myPlugin.defaults = {
        name: "",
        color: "",
        car: ""
    };

    function debug(el) {
        console.log('opts_' +el);
        console.log(opts);
        console.log('globalParams_' +el);
        console.log(globalParams);
    }

})(jQuery, window, document);

multi-instante插件

$(function() {
    $('#one').myPlugin({
        name: "Bar",
        color: "blue",
        car: "Audi"
    });

    $('#two').myPlugin({
        name: "Foo",
        color: "red",
        car: "BMW"
    });
});

HTML

<div id="one"><button class="btn">Click ONE</button></div>
<div id="two"><button class="btn">Click TWO</button></div>

这是(init)调试调用的日志,没关系。

//opts_one = Object { name="Bar",  color="blue",  car="Audi"}
//globalParams_one = Object { name="Bar",  color="blue",  car="Audi"}

//opts_two = Object { name="Foo",  color="red",  car="BMW"}
//globalParams_two = Object { name="Foo",  color="red",  car="BMW"}

现在,如果我点击#one btn,我的结果总是如此。这是错的!

//opts_one = Object { name="Foo",  color="red",  car="BMW"}
//globalParams_one = Object { name="Foo",  color="red",  car="BMW"}

我认为插件全局变量仅在插件范围内是全局的。 错在哪里?我该怎么办?谢谢

1 个答案:

答案 0 :(得分:1)

外部作用域不能用于特定于插件的任何特定调用的数据。

通常使用jQuery的.data()对每个初始化的DOM元素存储此类数据,而外部作用域用于静态数据和任何实用程序函数。

这也是典型的:

  • 将初始化代码编写为init方法。
  • 除了init之外,还允许使用其他插件方法,例如debug。包含destroy方法也是个好主意。

以下是一个例子:

;(function ($, window, document, undefined) {
    'use strict';

    //static vars
    var pluginName = 'myPlugin';

    // utility functions here
    ...

    var methods = {
        init: function(options) {
            var that this;
            var data = this.data(pluginName);
            if(!data) { // if plugin has not been initialized on this element
                var defaults = {
                    name: "",
                    color: "",
                    car: ""
                };
                var opts = $.extend(true, defaults, options);
                this.data(pluginName, {
                    name: opts.name,
                    color: opts.color,
                    car: opts.car,
                    el: this.attr('id')
                });
                this.on('click.' + pluginName, '.btn', function() {
                    methods.debug.call($(that));
                });
            }
        },
        debug: function () {
            var data = this.data(pluginName);
            console.dir(data);
        },
        destroy: function () {
            this.data(pluginName, null);
            this.off('click.' + pluginName);
        }
        // ... other methods
    };

    $.fn[pluginName] = function(options) {
        options = options || {};
        return this.each(function() {
            var method = options.method || 'init';
            if(methods[method]) {
                methods[method].call($(this), options);
            }
        });
    };
})(jQuery, window, document);

未测试

请注意,插件本身只是一个小的管理程序函数,它决定使用哪种方法,然后调用它。更好(也更复杂)的主管版本允许该方法与options分开指定 - 例如见here

调用如下:

$(function() {
    $('#one').myPlugin({
        name: "Bar",
        color: "blue",
        car: "Audi"
    }).myPlugin({method:'debug'});

    $('#two').myPlugin({
        name: "Foo",
        color: "red",
        car: "BMW"
    }).myPlugin({method:'debug'});
});