出于练习目的,我正在创建一个jQuery插件,一个简单的图像滑块。我使用Boilerplate - jQuery Plugins中的模式。
在初始化过程中,一切都按预期工作,每个实例都获得设置所需的正确值(宽度和高度,也包括事件绑定)。
当我尝试将计算出的slide-width传递给执行动画的函数(单击下一个按钮)时,麻烦就开始了。我试图保存的每个值都被最后一个实例覆盖 - 好吧,这就是我所学习的原型继承所做的事情。
我搜索了很多,并且在库存溢出中找到了(不仅仅是)这个解决方案:global or local variables in a jquery-plugin。接受的答案建议存储HTML标记中需要私有的值,data-whatever属性。
这非常好,但不是很好。
第二个答案似乎更优雅,将真实的私有变量保留在每个实例的范围内:
(function($) {
$.pluginName = function(element, options) {
....
var plugin = this;
....
// a public method
plugin.foo_public_method = function() {
....
}
// private methods
var foo_private_method = function() {
....
}
plugin.init();
} ....
看起来非常简单 - 但我无法实现此解决方案!
所以我的问题是:如何在以下插件模式中实现私有变量?(如何从Plugin.prototype中正确调用它...)
我用我的插件创建了一个Fiddle。代码摘要:
(function ($, window, document, undefined) {
var pluginName = "easyCarousel";
// default configuration object
defaults = {
... default values here, css etc
}
};
// The actual plugin constructor
function Plugin(element, options) {
this.element = element;
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
var options = this.options;
this.options.stage = $(this.element);
.... calling/starting views and controllers
},
buildCollectionView: function (options, Helper) {
.... setting markup, applying css, calulating dimensions
},
buildStageView: function (options, Helper) {
.... setting markup, applying css
.... storing calculated slide width in data Attribute
stage.attr({
'data-slidewidth': width,
'data-stagewidth': setWidth
});
},
buildTheatreView: function (options, Helper) {
.... setting markup, applying css
},
buildNavigationView: function (options) {
.... setting markup
},
navigationController:
function (options, slideForward, slideBackward) {
.... event binding
pubSub.on("navigation:arrownext:click", function (e) {
slideForward(options, e);
});
$('.carousel__arrownext', options.theatre)
.bind('click', function () {
pubSub.trigger("navigation:arrownext:click", this);
});
},
slideForwardAnimation: function (options, e) {
.... reading stored width value from data Attribute
$element.animate({
"left": "-=" + slideWidth
})
},
setDimensionsHelper: function (options) {
.... calculating an returning dimensions of the slider
},
eventBusHelper: function (options) {
// integrating third party eventbus
}
};
$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName,
new Plugin(this, options));
}
});
}})(jQuery, window, document);
我希望我的代码示例不会复杂/长时间查看。
正如您所看到的,我对高级Javascript模式非常陌生 - 而且现在我真的卡住了。我已经花了很多时间来解决这个问题。因此,非常感谢每一次提供帮助的尝试。当然还有关于代码的每一次评论。
提前致谢:)
答案 0 :(得分:3)
您需要做的就是在原型中定义变量(直接或在原型中的方法内),而不是在构造函数中进行。构造函数中定义的变量将在插件的所有实例之间共享,而原型中定义的变量将是每个实例。
另外,你没有" var"您的"默认值"前面的关键字定义,所以你实际上创建了一个名为"默认值"的全局变量。而不是仅限于你关闭的那个。
这是我建议的:
// default configuration object
var defaults = {
... default values here, css etc
}
};
// The actual plugin constructor
function Plugin(element, options) {
this._defaults = defaults;
this._name = pluginName;
this.init(element, options);
}
Plugin.prototype = {
init: function (element, options) {
this.element = element;
this.options = $.extend({}, this._defaults, options);
this.options.stage = $(this.element);
.... calling/starting views and controllers
},
甚至更好:
// The actual plugin constructor
function Plugin(element, options) {
this.init(element, options);
}
Plugin.prototype = {
_name: 'put your name here',
_defaults: {
// just define them here, no need for an outside variable
},
init: function (element, options) {
this.element = element;
this.options = $.extend({}, this._defaults, options);
// why are you saving stage as an option? That doesn't make sense.
this.options.stage = $(this.element);
// Makes more sense to just do this ($el is a more standard name for this)
this.$el = $(this.element);
// .... calling/starting views and controllers
},