带有属于给定插件实例的"本地"变量的jQuery插件

Cha*_*had 5 javascript jquery scope jquery-plugins

我正在研究一个jQuery插件,但我遇到了变量"范围"的问题.每个插件都需要跟踪一个相当大的多维数组,以及jQuery插件所附加的根元素.

如下所示,我已经定义var $rootEl = null;var multidArray = null;在插件代码的顶部; 但是,当我$(anySelector).pluginName("value");在多个元素上运行时(或者当我.pluginName()使用不同的选择器调用两次)时,看起来这些变量不会被沙箱化/作用于插件实例,因此第二个实例会覆盖这两个值,第一个实例看起来为空白在DOM中(因为所有jQuery操作都应用于$rootEl第二个jQuery插件调用时覆盖的原始值).

(function ($) {

    var $rootEl = null;
    var multidArray = null;

    directChildren = function(uuid) {

        return $rootEl.children("[data-uuid=" + uuid + "]");

    },

    incrementCounter = function() {
        this.counter++;
    },

    resetGenIteration = function() {
        this.counter = 0;
    },

    process = function(item) { // Will be called from a callback(val) in another
        // javascript file but still needs to have access to the local variables
        // of the current jQuery plugin

        incrementCounter();

        ...

    },

    ...

    $.fn.pluginName = function(rootvar) {

        this.each(function() {

            $rootEl = $(this);

            resetGenIteration();
            populate(rootvar);

            $rootEl.addClass("pluginName").delegate("div", "click", divClick);

        });

    }

}(jQuery));
Run Code Online (Sandbox Code Playgroud)

昨天我试图插件使用init和转换this.varname存储的值,它似乎守住this.$rootEl正确属性为插件的每个实例,但我不得不搬到里面我的所有功能var PluginName = { ... },并切换他们funcName = function()funcName: function()能够查看插件实例的"本地"变量.然后我遇到了许多错误,其中没有定义函数,所以我试着用我的所有函数调用作为前缀this.和分别PluginName.读取this.functionName()PluginName.functionName()分别用于某些函数,但不是全部.我的一些函数是从另一个jQuery插件调用的,它运行一个回调函数并将数据传递给它,在这些情况下this.$rootEl变成了undefined.

(function ($){

    var PluginName = {

        init: function(options, rootEl) {

            this.options = $.extend({}, this.options, options);

            this.rootEl  = rootEl;
            this.$rootEl = $(rootEl);

            this.setListeners();

            return this;

        },

        options: {
            rootvar: "test"
        },

        ...

        setListeners:function (){

            var self = this;

            this.$rootEl.on("div", "click", function () {
                $.proxy(self.divClick, self);
            });

        }

    };

    ...

    $.fn.pluginName = function(options) {

        this.init = function(options, rootEl) {

            this.options = $.extend({}, this.options, options);

            this.rootEl  = rootEl;
            this.$rootEl = $(rootEl);
            this.multidArray = null;


            return this;

        };

        this.each(function() {

            var plugInstance = Object.create(PluginName);
            plugInstance.init(options, this);
            $.data(this, 'pluginName', plugInstance);

        });

    }

}(jQuery));
Run Code Online (Sandbox Code Playgroud)

我如何重构我的代码来存储多维数组和根元素,只有那个给定的插件才能在内部检索和修改?当然我不应该.data()用于大型阵列?

谢谢!

Dam*_*mon 1

插件只是附加到 jQuery 对象的一个​​函数。它没有多个实例,但可以多次调用。每次调用都会创建一个新的作用域,但是,在pluginName函数外部声明的变量将被每次调用共享。

我建议您重新使用多个函数,而不是在第二次迭代中尝试使用面向对象的方法。但是,您可以向这些函数传递所有必需的参数,这样它们就不必依赖于不明确的this值。

由于您只包含了代码的部分片段,因此我无法清楚地了解您想要完成的任务,但我在下面包含了一个示例插件,重点介绍了如何正确使用范围。

(function ($) {
  // declare variables that can be shared by every call of "pluginName" here

  var defaultColor = 'green'

  // passing the element as an argument means we don't have to rely on ambiguous 'this'.
  function someTransformation ($el, someColor) {
    return $el.css({backgroundColor: someColor})
  }


  $.fn.pluginName = function (color, idx) {
    // declare variables that should be reinitialized on every call of "pluginName" here
    var els = []

    this.each(function () {
      var $el = $(this)
      someTransformation($el, defaultColor)
      els.push($el)
    })

    // we can still use the array we stored
    if (els[idx]) {
      someTransformation(els[idx], color)
    }
  }
})($)

$('#first i').pluginName('red', 2)
$('#second i').pluginName('blue', 0)
Run Code Online (Sandbox Code Playgroud)
i {
  display: inline-block;
  width: 50px;
  height: 50px;
  margin: 10px;
}

div {
 border: 1px solid black;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="first">
 <i></i><i></i><i></i><i></i>
</div>

<div id="second">
  <i></i><i></i><i></i><i></i>
</div>
Run Code Online (Sandbox Code Playgroud)

如果您仍然遇到问题,请从执行该函数中的所有操作pluginName开始。无需声明额外的助手。这将帮助您确保所有逻辑都正常工作。然后开始将任何重用的代码移至辅助函数中,该函数接受运行所需的所有参数。

有些相关但不是立即有用的挑剔:pluginName (directChildren例如) 之外的函数表达式是全局变量。确保在这些内容前面加上 ,var以确保它们的范围仅限于您的 IIFE 。