在jQuery插件成员中正确获取“this”

时间:2015-03-03 16:34:41

标签: javascript jquery jquery-plugins

我有一个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);

我面临的问题是我无法在.add()中使用“this”。 我设法做到的最好方法是不要让Foo自我初始化, 并使用如下语法:

$.fn.foo = Foo;
$(elem).foo().add(a);

它有效,但我发现它不那么美观,不那么“干净”。

有办法做到这一点吗?我完全是错误的做法吗?

感谢任何输入,如果已经得到回答或者其他方式不合适,我会提前道歉。 我确实在寻找答案,但我并不精通插件创作,也不是jQuery本身的专家。

TL; DR:我上面有一个像Foo这样的模块,并希望像jQuery插件一样访问它的成员。

1 个答案:

答案 0 :(得分:1)

这是我通常使用的模式的简化版本(错误检查和删除的额外功能)。

它使用单个类函数和插件桥扩展方法来允许附加到多个元素。通过使用字符串选项值调用方法:

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从元素文本中获取初始值,然后"添加"调用修改该值。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/

注意:

  • ~~只是parseInt()
  • 的快速捷径
  • 您可以通过options参数提供初始值(在第一个示例中忽略)。见如下:

e.g。

// 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});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/4/