正确获取 "this" in jQuery 插件成员
Properly get "this" in jQuery plugin member
我有一个 JavaScript 模块,我想为其创建一个 jQuery 插件接口。
模块本身是这样的:
var Foo = (function () {
"use strict";
var self = {};
self.add = function (selector, otherParam)
{
// Does things unto selector.
// Precisely what it does doesn't matter.
};
return self;
}());
并被使用,成功,像这样:
Foo.add(a);
现在,我想创建一个与该模块接口的插件,
所以我可以像这样使用它:
$.fn.foo = Foo;
$.fn.foo.add = function (param) {
var selector = this;
Foo.add(selector, param);
}
$(elem).foo.add(a);
我面临的问题是我无法 "this" 在 .add() 中工作。
我设法做到这一点的最好方法是不要让 Foo 进行自我初始化,
并使用如下语法:
$.fn.foo = Foo;
$(elem).foo().add(a);
它有效,但我发现它在美学上不那么令人愉悦,也不那么 "clean"。
有办法吗?我是不是完全走错了路?
感谢您的任何意见,如果此问题已得到答复或以任何其他方式不合适,我提前致歉。
我确实搜索了答案,但我并不精通插件创作,也不是 jQuery 本身的专家。
TL;DR: 我有一个像上面 Foo 这样的模块,我想像 jQuery 插件一样访问它的成员。
这是我通常使用的模式的简化版本(删除了错误检查和额外功能)。
它使用一个 class 函数和一个 插件桥 扩展方法来允许附加到多个元素。使用字符串选项值调用方法:
var Foo = (function () {
"use strict";
// Constructor
function Foo($element, options){
this.$element = $element;
this.options = options
this.fooVal = 0;
}
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = ~~this.$element.text()
};
// Add the specified val to the elements current value
Foo.prototype.add = function (val) {
this.fooVal += val;
// Update the element text with the new value
this.$element.text(this.fooVal);
};
return Foo;
})();
// Create a bridge to each element that needs a Foo
$.fn.foo = function (options, args) {
this.each(function () {
var $element = $(this);
// Try to get existing foo instance
var foo = $element.data("Foo");
// If the argument is a string, assume we call that function by name
if (typeof options == "string") {
foo[options](args);
}
else if (!foo) {
// No instance. Create a new Foo and store the instance on the element
foo = new Foo($element, options);
$element.data("Foo", foo);
// Record the connected element on the Foo instance
foo.$element = $element;
// Call the initial create method
foo.onCreate();
}
});
}
// testing
console.clear();
$('#test').foo();
$('#button2').click(function () {
$('#test').foo("add", 2);
});
$('#button10').click(function () {
$('#test').foo("add", 10);
});
对于您的示例,Foo
从元素文本中获取初始值,随后的 "add" 调用会修改该值。
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/
备注:
~~
只是 parseInt()
的快捷方式
- 您可以通过选项参数提供初始值(在第一个示例中被忽略)。请参阅以下内容:
例如
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = this.options.value || ~~this.$element.text()
// Set initial value
this.$element.text(this.fooVal);
};
并从
开始
$('#test').foo({value: 999});
我有一个 JavaScript 模块,我想为其创建一个 jQuery 插件接口。 模块本身是这样的:
var Foo = (function () {
"use strict";
var self = {};
self.add = function (selector, otherParam)
{
// Does things unto selector.
// Precisely what it does doesn't matter.
};
return self;
}());
并被使用,成功,像这样:
Foo.add(a);
现在,我想创建一个与该模块接口的插件, 所以我可以像这样使用它:
$.fn.foo = Foo;
$.fn.foo.add = function (param) {
var selector = this;
Foo.add(selector, param);
}
$(elem).foo.add(a);
我面临的问题是我无法 "this" 在 .add() 中工作。 我设法做到这一点的最好方法是不要让 Foo 进行自我初始化, 并使用如下语法:
$.fn.foo = Foo;
$(elem).foo().add(a);
它有效,但我发现它在美学上不那么令人愉悦,也不那么 "clean"。
有办法吗?我是不是完全走错了路?
感谢您的任何意见,如果此问题已得到答复或以任何其他方式不合适,我提前致歉。 我确实搜索了答案,但我并不精通插件创作,也不是 jQuery 本身的专家。
TL;DR: 我有一个像上面 Foo 这样的模块,我想像 jQuery 插件一样访问它的成员。
这是我通常使用的模式的简化版本(删除了错误检查和额外功能)。
它使用一个 class 函数和一个 插件桥 扩展方法来允许附加到多个元素。使用字符串选项值调用方法:
var Foo = (function () {
"use strict";
// Constructor
function Foo($element, options){
this.$element = $element;
this.options = options
this.fooVal = 0;
}
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = ~~this.$element.text()
};
// Add the specified val to the elements current value
Foo.prototype.add = function (val) {
this.fooVal += val;
// Update the element text with the new value
this.$element.text(this.fooVal);
};
return Foo;
})();
// Create a bridge to each element that needs a Foo
$.fn.foo = function (options, args) {
this.each(function () {
var $element = $(this);
// Try to get existing foo instance
var foo = $element.data("Foo");
// If the argument is a string, assume we call that function by name
if (typeof options == "string") {
foo[options](args);
}
else if (!foo) {
// No instance. Create a new Foo and store the instance on the element
foo = new Foo($element, options);
$element.data("Foo", foo);
// Record the connected element on the Foo instance
foo.$element = $element;
// Call the initial create method
foo.onCreate();
}
});
}
// testing
console.clear();
$('#test').foo();
$('#button2').click(function () {
$('#test').foo("add", 2);
});
$('#button10').click(function () {
$('#test').foo("add", 10);
});
对于您的示例,Foo
从元素文本中获取初始值,随后的 "add" 调用会修改该值。
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/
备注:
~~
只是parseInt()
的快捷方式
- 您可以通过选项参数提供初始值(在第一个示例中被忽略)。请参阅以下内容:
例如
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = this.options.value || ~~this.$element.text()
// Set initial value
this.$element.text(this.fooVal);
};
并从
开始$('#test').foo({value: 999});