jQuery插件模式:更面向对象的东西?

时间:2011-07-13 15:31:52

标签: javascript jquery jquery-plugins

我正在研究jQuery插件,遵循Authoring指南中详述的模式。基本上是:

(function($) {
  // Private
  var doSomething = function($element, settings) { ... }

  var doSomethingElse = function($element, settings) { ... }

  // Public
  var methods = {
    init: function(options) { ... },
    show: function() { ... },
    hide: function() { ... },
    update: function(content) { ... }
  };

  $.fn.myPlugin = function(method) {
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || ! method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' +  method + ' does not exist on jQuery.myPlugin');
    }
  };
})(jQuery);

这是我的不喜欢:我必须将相同的“实例”变量传递给所有私有函数。我仍然在努力成为一名JS专业人员 - 请原谅我不正确的术语用法 - 但如果我在Ruby或PHP中做同样的事情,我会创建一个包含所有这些公共和私有成员和方法的类,每个该类的实例将对应于$element。然后我可以做这样的事情(在JS中):

var firstElement = new MyPlugin($element, settings);
firstElement.doSomething();

不是将$elementsettings传递给doSomething(),而是已经可以通过this.$elementthis.settings访问这些内容。

到达我要去的地方?我想,我正在寻找一种更加面向对象的方法。现在,我完全理解JS没有类似Ruby或PHP的类。但是在构造函数,模块模式和常规对象表示法(如上面的methods)之间,我不确定哪个是jQuery插件的最佳选择。

有人可以帮助我指出正确的方向吗?也许现有jQuery插件的一些例子可以很好地做到这一点?谢谢!

2 个答案:

答案 0 :(得分:5)

jQuery UI Widget Factory可能是一个很好的解决方案。它对于创建任何类型的有状态jQuery插件很有用,并且可以与jQuery UI套件的其余部分完全分开使用。

一些有用的链接:


如果你想要一个更简单的骨骼解决方案,我会选择常规的Constructor + prototype设置来“正确”执行操作,或者使用Revealing Module Pattern创建一个将元素和任何选项作为参数并返回的函数公共方法。

使用揭示模块模式的示例:

function myPlugin (element, options) {
    var privateVar;

    function privateFunc () {}

    function publicMethod () {}

    return {
        publicMethodName: publicMethod
    };
}

这种模式比传统的原型设置更整洁,但没有利用原型链。

编辑:为了澄清,在使用任何这些模式时,您应该为每个元素/用途创建一个新实例。

答案 1 :(得分:2)

在插件本身中存储任何类型的有状态信息不一定是个好主意,因为它将由所有实例共享。一种选择是将数据存储在插件之外的其他位置。

Plugins/Authoring page has a Data section,其中介绍了如何使用data()函数在每个元素的基础上存储插件使用的信息。

  

使用数据可帮助您跟踪方法中的变量和状态   来自你的插件的电话。命名将数据空间分配到一个对象文字中   可以轻松地从一个插件中访问所有插件的属性   中心位置,以及减少允许的数据命名空间   如果需要,可以轻松移除。

页面上提供的示例使用帖子中描述的插件模式,但允许“实例”变量与它们关联的元素一起存储。

执行此操作时要记住的一件事是:

  

始终命名方法,事件和数据。

修改

还应该注意,在您的示例中,您的某些函数需要$element作为参数,但这不是必需的,因为this将引用正确的东西当通过插件调用这些函数时(因为正在调用apply()并将上下文设置为正确的this)。