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()用于大型阵列?
谢谢!
插件只是附加到 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 。