Я уже довольно давно разрабатываю плагины jQuery, и мне нравится думать, что я уже хорошо знаю, как их проектировать. Однако меня не покидает одна проблема, а именно - как справиться с частными функциями мощным, но элегантным способом.
Мои плагины обычно выглядят примерно так:
(function($) {
$.fn.myplugin = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'green');
...
};
$.fn.mypluginAnotherPublicMethod = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'red');
...
};
}(jQuery));
Теперь мой вопрос: как аккуратно СУШИТЬ эту общую функциональность? Очевидным решением было бы поместить его в функцию в пространстве имен плагина:
var fill = function($obj, color) {
$obj.css('background-color', color);
};
Хотя это решение является эффективным и имеет красивое пространство имен, мне оно очень не нравится. По одной простой причине: я должен передать ему объект jQuery. Т.е. Я должен называть это так: fill(this, 'red');
, а я хотел бы называть это так: this.fill('red');
Конечно, мы могли бы достичь этого результата, просто поместив fill
в jQuery.fn
. Но это очень неудобно. Представьте, что на основе этого подхода разработано десять плагинов, и каждый плагин помещает пять из этих «частных» функций в пространство имен функций jQuery. Это заканчивается большим беспорядком. Мы могли бы смягчить это, добавив к каждой из этих функций префикса имени плагина, которому они принадлежат, но это не делает ее более привлекательной. Эти функции должны быть частными для плагина, поэтому мы вообще не хотим открывать их внешнему миру (по крайней мере, не напрямую).
Итак, у меня есть вопрос: есть ли у кого-нибудь из вас предложения, как получить лучшее из обоих миров? То есть; код плагина, способный вызывать «частные» функции плагина аналогично this.fill('red')
(или this.myplugin.fill('red')
, или даже this.myplugin().fill('red')
и т. д.), предотвращая при этом загрязнение пространства имен функций jQuery. И, конечно же, он должен быть легким, поскольку эти частные функции могут вызываться очень часто.
ОБНОВЛЕНИЕ: спасибо за ваши предложения.
Мне особенно нравится идея Дэвида определить тип объекта, который содержит «частные» функции и обертывает объект jQuery. Единственная проблема в том, что он по-прежнему не позволяет мне связывать «частные» и «общедоступные» функции. Это было серьезной причиной, по которой нужно начинать с синтаксиса типа this.fill('red')
.
В итоге я получил решение, которое считаю не слишком элегантным, но привлекательным для «лучшего из обоих миров», потому что:
$.fn.chain = function(func) {
return func.apply(this, Array.prototype.slice.call(arguments, 1));
};
Это позволяет создавать такие конструкции, как:
this.
find('.acertainclass').
chain(fill, 'red').
click(function() {
alert("I'm red");
});
Я разместил свой вопрос в других местах, где тоже собраны интересные ответы: