[英]How can I give a plugin's default settings access to the final settings?
I'm working on a jQuery plugin. 我正在研究一个jQuery插件。 When the plugin runs, the first thing it does is determine its settings.
当插件运行时,它首先要确定它的设置。 It does this by taking some default settings and overriding some or all of them with whatever the user passed in.
它通过采用一些默认设置并使用用户传入的任何内容覆盖部分或全部设置来实现此目的。
Here's a simplified version: 这是一个简化版本:
(function( $ ) {
$.fn.somePlugin = function(userOptions) {
// Short name for internal use - exposed below for external modification
var defaults = $.fn.somePlugin.defaults;
// Decide settings
// User settings overrule defaults, but merge both into an empty
// hash so that original defaults hash isn't modified
var settings = $.extend(true, {}, defaults, userOptions);
settings.alerter.call();
// More code, etc.
}
$.fn.somePlugin.defaults = {
name: 'Captain Slappy von Martinez, Esquire, DDS',
favoriteColor: 'red',
alerter: function(){alert("I got bones!");}
}
})( jQuery );
So, if you call the plugin like this: 所以,如果你像这样调用插件:
$('div').somePlugin({alerter: function(){alert('No bones here!');}});
... you override the default alerter
function, but use the default favoriteColor
. ...您覆盖默认
alerter
功能,但使用默认的favoriteColor
。
I'm defining the defaults outside the plugin itself so that they are publicly accessible. 我在插件本身之外定义默认值,以便它们可以公开访问。 So if you want to change the default value for
favoriteColor
, you can just do this: 因此,如果您想更改
favoriteColor
的默认值,您可以这样做:
$.fn.somePlugin.defaults.favoriteColor = 'blue';
... and that will change it for every instance on the page after that. ......之后,这会改变页面上每个实例的内容。
All of this works fine. 所有这一切都很好。
Here's my problem: in one of the default functions, I need to refer to settings
. 这是我的问题:在其中一个默认函数中,我需要参考
settings
。 Something like this: 像这样的东西:
$.fn.somePlugin.defaults = {
name: 'Captain Slappy von Martinez, Esquire, DDS',
favoriteColor: 'red',
alerter: function(){alert("Paint me " + settings.favoriteColor);}
}
But when I try this, I get a Javascript error on the line where the default alerter function is declared: "settings is not defined." 但是当我尝试这个时,我在声明默认警报器功能的行上得到一个Javascript错误:“设置未定义”。 True enough: it's not defined yet when the parser hits that line.
确实如此:当解析器命中该行时,它尚未定义。 It WILL be defined by the time the function runs, but that doesn't seem to matter.
它将由函数运行的时间定义,但这似乎并不重要。
So my question is: How can I import my default function into the plugin in such a way that it has access to settings
? 所以我的问题是: 如何以一种可以访问
settings
的方式将我的默认功能导入插件?
settings
until the function is actually called? settings
评估,直到实际调用该函数? this
inside a function by using someFunction.call(valueToUseForThis)
, but I don't know whether I can alter its scope after the fact. this
为通过功能里面someFunction.call(valueToUseForThis)
但我不知道我是否能在事后改变其范围。 settings
in the outer, self-executing function, that would make it available to the defaults. settings
,那么它将使其可用于默认值。 But declaring it there causes problems: if I use my plugin multiple times on a page, the instances get their settings mixed up. Any attempts to change scope after the fact are doomed. 任何事后改变范围的企图都注定要失败。 There's no dynamic scoping in JavaScript.
JavaScript中没有动态范围。
Workaround 1. Pass settings to the alerter explicitly: 解决方法1.明确地将设置传递给警报器:
$.fn.somePlugin = function(userOptions) {
var settings = $.extend(...);
settings.alerter(settings)
}
$.fn.somePlugin.defaults = {
favoriteColor: 'red',
alerter: function(settings) { alert("Paint me " + settings.favoriteColor) }
}
Workaround 2. Pass settings to the alerter implicitly: 解决方法2.隐式将设置传递给警报器:
$.fn.somePlugin = function(userOptions) {
var settings = $.extend(...);
settings.alerter()
}
$.fn.somePlugin.defaults = {
favoriteColor: 'red',
alerter: function() { alert("Paint me " + this.favoriteColor) }
}
Both solutions tested and work well with multiple uses of the plugin. 两种解决方案都经过测试,并且可以很好地使用插件。 If you have no plans for using
this
keyword in your alerter, you can use it for referencing settings. 如果您没有计划在警报器中使用
this
关键字,则可以将其用于引用设置。
The third valid solution , which you and fudgey mentioned, is to attach settings object to the DOM element itself: 你和fudgey提到的第三个有效的解决方案是将设置对象附加到DOM元素本身:
$.fn.somePlugin = function(userOptions) {
var settings = $.extend(...);
$(this).data('somePlugin', {settings: settings})
settings.alerter.call(this)
}
$.fn.somePlugin.defaults = {
favoriteColor: 'red',
alerter: function() {
alert("Paint me " + $(this).data('somePlugin').settings.favoriteColor)
}
}
Extra fun. 额外的乐趣。 Emulating dynamic scope, aka don't do this
模拟动态范围, 也就是说不要这样做
function dynamic(fn) {
var parts = fn.toString().split('{')
fn = parts.shift() + '{ with (args) { ' + parts.join('{') + '}'
return {bind: function(args) { return eval('(' + fn + ')') }}
}
a = b = c = 0
function adder(c) {
alert(a + b + c)
}
dynamic(adder).bind({a: 1, b: 2})(3) // alert(6)
Usage in a plugin: 插件中的用法:
$.fn.somePlugin = function(userOptions) {
var settings = $.extend(...);
dynamic(settings.alerter).bind({settings: settings})()
}
$.fn.somePlugin.defaults = {
favoriteColor: 'red',
alerter: function() { alert("Paint me " + settings.favoriteColor) }
}
The settings
variable is scoped to the $.fn.somePlugin
function so it is not available outside of this, which is where you're trying to reference it in $.fn.somePlugin.defaults
. settings
变量的范围限定为$.fn.somePlugin
函数,因此它在此之外不可用,这是您尝试在$.fn.somePlugin.defaults
引用它的$.fn.somePlugin.defaults
。 Can you not simply move the default object inside $.fn.somePlugin
and declare it in there? 你能不能简单地在
$.fn.somePlugin
移动默认对象并在那里声明它?
Try this (code untested): 试试这个(代码未经测试):
(function( $ ) {
$.fn.somePlugin = function(userOptions) {
// Short name for internal use - exposed below for external modification
var settings = {},
defaults = {
name: 'Captain Slappy von Martinez, Esquire, DDS',
favoriteColor: 'red',
alerter: function(){alert("Paint me " + settings.favoriteColor);}
};
// Decide settings
// User settings overrule defaults, but merge both into an empty
// hash so that original defaults hash isn't modified
settings = $.extend(true, {}, defaults, userOptions);
settings.alerter.call();
// More code, etc.
}
})( jQuery );
Edit : In light of your comment below, the simplest approach is probably to just move the declaration of settings up a level into the outer function - being locally scoped to this function, it will still be private to external callers. 编辑 :根据您在下面的评论,最简单的方法可能是将设置声明向上移动到外部函数 - 本地作用于此函数,它仍然是外部调用者的私有。 Revised code below:
修改后的代码如下:
(function( $ ) {
var settings = {}
$.fn.somePlugin = function(userOptions) {
// Decide settings
// User settings overrule defaults, but merge both into an empty
// hash so that original defaults hash isn't modified
settings = $.extend(true, {}, $.fn.somePlugin.defaults, userOptions);
settings.alerter.call();
// More code, etc.
}
$.fn.somePlugin.defaults = {
name: 'Captain Slappy von Martinez, Esquire, DDS',
favoriteColor: 'red',
alerter: function(){alert("Paint me " + settings.favoriteColor);}
}
})( jQuery );
$.fn.somePlugin.defaults.favoriteColor = 'blue';
$.fn.somePlugin(); // Should alert 'Paint me blue'
alert(settings.favoriteColour) // Will not work here;
Simply change settings
to this
: 简单地更改
settings
来this
:
$.fn.somePlugin.defaults = {
name: 'Captain Slappy von Martinez, Esquire, DDS',
favoriteColor: 'red',
alerter: function () { alert("Paint me " + this.favoriteColor); }
}
That's it! 而已!
EDIT: Oh! 编辑:哦! I just noticed something in your code!
我刚注意到你的代码中有些东西! Don't use
.call()
to call settings.alerter
. 不要使用
.call()
来调用settings.alerter
。 That changes the meaning of this
. 改变的意思
this
。 Just call the method directly. 只需直接调用该方法即可。 If you must use
.call()
, pass in settings
as the parameter for this
. 如果你必须使用
.call()
传递settings
作为参数this
。
settings.alerter.call(); // this won't work.
settings.alerter(); // but this will!
settings.alerter.call(settings); // this works too
Here's a complete working example based on your code: http://jsfiddle.net/gilly3/k2Eep/2/ 以下是基于您的代码的完整工作示例: http : //jsfiddle.net/gilly3/k2Eep/2/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.