将类附加到 jQuery 对象
我正在为如何最好地结合 javascript 类和 jQuery 插件而苦苦挣扎.这个问题不是很具体,我希望的是指向更多资源的指针.
I'm struggling with how best to combine javascript Classes and jQuery plugins. This question isn't very specific, what I'm hoping for is pointers to more resources.
基本上,我想将状态数据和私有方法存储在一个类中,然后扩展我调用插件的每个 jQuery 对象以具有这些私有方法和属性.这样我就可以在插件内部直接调用 jQuery 对象的方法.
Basically, I want to store state data and private methods in a class, and then extend each jQuery object which I call my plugin on to have those private methods and properties. Such that inside the plugin I can call methods directly off the jQuery object.
我阅读了 jQuery 插件设计模式(常见做法?)用于处理私有函数,特别是大卫的回答,但是每次都会初始化一个新类,因此不能用于保存对象的状态.
I read jQuery plugin design pattern (common practice?) for dealing with private functions, specifically David's answer, however this initializes a new Class each time, and thus can't be used to save the state of the object.
我还发现 http://fuelyourcoding.com/jquery-plugin-design-patterns-part-i/,建议创建一个类,然后将其存储在 .data() 中.
I also found http://fuelyourcoding.com/jquery-plugin-design-patterns-part-i/, which recommends creating a class and then storing it in .data().
我认为理想情况下我想要的代码看起来像
I think ideally what I want to end up with is code that looks like
(function( $ ){
var methods = {
init : function( options ) { // Initialize each object with a state and private methods },
show : function( ) {
// testFoo() is a private method that checks the element's state
if(this.testFoo()){
// Relying on jQuery's html() method
this.html() = this.fooTemplate();
}
}
};
// Boiler plate plugin from http://docs.jquery.com/Plugins/Authoring
$.fn.myPlugin = function( method ) {
// Method calling logic
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 );
最后,我似乎无法将私有方法直接烘焙到插件中,因为像testFoo()"这样的方法将返回一个布尔值,因此不可链接.
Finally, it doesn't seem like I can bake the private methods into the plugin directly because methods like "testFoo()" will return a boolean, and therefore aren't chainable.
想法?我以正确的方式接近这个吗?我应该使用另一种设计模式吗?也许根本不使用 jQuery 插件架构?
Thoughts? Am I approaching this the right way? Is there another design pattern I should be using? Perhaps not using jQuery plugin architecture at all?
推荐答案
这是一个建议的解决方案.它结合了几种不同的方法(John Resig 的继承模型和 Alex Saxton 的插件继承模型).
Here's a proposed solution. It combines few different approaches (John Resig's inheritance model and Alex Saxton's plugin inheritance model).
定义您的可继承插件:
(function ($) {
My.Plugin = Class.extend({
/*
* Initialization (constructor)
*/
init: function (element, meta) {
var $meta = $.extend({ name: "pluginName" }, meta);
// Call the base constructor
this._super(element, $meta);
// TODO: Add custom initialization code like the following:
// this._testButton = $('.testButton', element).get(0);
},
/*
* Public methods
*/
show: function() {
alert('This is a public method');
},
/*
* Private methods
*/
// DEMO: Overriding the base _paint method:
_paint: function () {
// "this._super()" is available in all overridden methods
// and refers to the base method.
this._super();
alert('TODO: implement myPlugin._paint!');
}
});
// Declare this class as a jQuery plugin
$.plugin('my_plugin', My.Plugin);
})(jQuery);
定义基类
(function () {
var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /_super/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function () { };
// Create a new Class that inherits from this class
Class.extend = function (prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] =
typeof prop[name] == "function"
&& typeof _super[name] == "function"
&& fnTest.test(prop[name])
? (function (name, fn) {
return function () {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name])
: prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
插件创建
(function ($) {
// The "inheritance plugin" model
// [http://alexsexton.com/?p=51][1]
$.plugin = function (name, object) {
$.fn[name] = function (options) {
var instance = $.data(this, name, new object(this, options));
return instance;
};
};
})(jQuery);
从 javascript 调用你的插件:
Calling your plugin from javascript:
$('#someElem').my_plugin({options: {}, data: {} /* you can modify your plugin code to accept anything */}).show();
注意:
这里的私有方法被标记为_methodName.这是纯粹的约定.如果你真的想隐藏它们,你可以使用模块模式(谷歌或者这里是一个初学者:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth)
Private methods here are marked as _methodName. It's pure convention. If you really want to hide them, you can use module pattern (google for it or here's one for starters: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth)
这就是你要找的吗?
相关文章