jQuery 插件开发如何保持变量和方法私有
jQuery Plugin Development how to keep variables and methods private
出于练习目的,我正在创建一个 jQuery 插件,一个简单的图像滑块。我使用 Boilerplate - jQuery Plugins.
中的模式
在初始化过程中,一切都按预期进行,每个实例都获得了设置所需的正确值(宽度和高度,以及事件绑定)。
当我尝试将计算出的幻灯片宽度传递给执行动画的函数(单击下一步按钮)时,问题就来了。我试图保存的每个值都被最后一个实例覆盖 - 好的,这就是原型继承所做的,正如我所了解的。
我在 google 上搜索了很多并在 stockoverflow 上找到了(不仅)这个解决方案: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);
希望我的代码示例不要complicated/long查看
如您所见,我对高级 Javascript 模式还很陌生 - 现在我真的卡住了。我已经在这个问题上花了很多时间。因此,我们非常感谢您的每一次帮助尝试。当然还有对代码的每次审查。
提前致谢:)
您需要做的就是在原型中定义变量(直接或从原型中的方法中),而不是在构造函数中进行。构造函数中定义的变量将在插件的所有实例之间共享,而原型中定义的变量将按实例共享。
此外,您的 "defaults" 定义前面没有 "var" 关键字,因此您实际上是在创建一个名为 "defaults" 的全局变量,而不是一个仅限于您的变量关闭。
这是我推荐的:
// 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
},
出于练习目的,我正在创建一个 jQuery 插件,一个简单的图像滑块。我使用 Boilerplate - jQuery Plugins.
中的模式在初始化过程中,一切都按预期进行,每个实例都获得了设置所需的正确值(宽度和高度,以及事件绑定)。
当我尝试将计算出的幻灯片宽度传递给执行动画的函数(单击下一步按钮)时,问题就来了。我试图保存的每个值都被最后一个实例覆盖 - 好的,这就是原型继承所做的,正如我所了解的。
我在 google 上搜索了很多并在 stockoverflow 上找到了(不仅)这个解决方案: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);
希望我的代码示例不要complicated/long查看
如您所见,我对高级 Javascript 模式还很陌生 - 现在我真的卡住了。我已经在这个问题上花了很多时间。因此,我们非常感谢您的每一次帮助尝试。当然还有对代码的每次审查。
提前致谢:)
您需要做的就是在原型中定义变量(直接或从原型中的方法中),而不是在构造函数中进行。构造函数中定义的变量将在插件的所有实例之间共享,而原型中定义的变量将按实例共享。
此外,您的 "defaults" 定义前面没有 "var" 关键字,因此您实际上是在创建一个名为 "defaults" 的全局变量,而不是一个仅限于您的变量关闭。
这是我推荐的:
// 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
},