Присоединение класса к объекту jQuery
Я борюсь с тем, как лучше сочетать классы JavaScript и плагины jQuery. Этот вопрос не очень конкретный, на что я надеюсь, это ссылки на дополнительные ресурсы.
По сути, я хочу хранить данные о состоянии и частные методы в классе, а затем расширять каждый объект jQuery, для которого я вызываю свой плагин, чтобы иметь эти частные методы и свойства. Так, что внутри плагина я могу вызывать методы непосредственно из объекта jQuery.
Я прочитал шаблон проектирования плагинов jQuery (общепринятая практика?) Для работы с частными функциями, в частности, с ответом Дэвида, однако он каждый раз инициализирует новый класс и, следовательно, не может использоваться для сохранения состояния объекта.
Я также нашел http://fuelyourcoding.com/jquery-plugin-design-patterns-part-i/, который рекомендует создать класс и затем сохранить его в.data().
Я думаю, в идеале, что я хочу закончить, это код, который выглядит как
(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()" будут возвращать логическое значение и, следовательно, не будут цепными.
Мысли? Правильно ли я подхожу к этому? Есть ли другой шаблон дизайна, который я должен использовать? Возможно, совсем не использовать архитектуру плагинов jQuery?
1 ответ
Вот предлагаемое решение. Он объединяет несколько разных подходов (модель наследования Джона Резига и модель наследования плагинов Алекса Сакстона).
Определите свой наследуемый плагин:
(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; }) ? /\b_super\b/ : /.*/;
// 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:
$('#someElem').my_plugin({options: {}, data: {} /* you can modify your plugin code to accept anything */}).show();
Замечания:
Частные методы здесь помечены как _methodName. Это чистое соглашение. Если вы действительно хотите скрыть их, вы можете использовать шаблон модуля (Google для него или вот для начала: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth)
Это то, что вы ищете?