Пространство имен плагинов jQuery
Как создать плагин jQuery, чтобы я мог использовать пространства имен в моем плагине?
$("#id1").amtec.foo1();
$("#id1").amtec.foo2();
Ни один из них не работает.
(function($) {
var amtec = {
$.fn.foo1 : function(){ return this.each(function(){}); },
$.fn.foo2 : function(){ return this.each(function(){}); }
};
})(jQuery);
(function($) {
$.fn.amtec = function(){
var foo1 = function(){ return this.each(function(){}); };
var foo2 = function(){ return this.each(function(){}); };
}
})(jQuery);
Ответы
Ответ 1
(function($) {
$.fn.amtec = function () {
var jq = this;
return {
foo1: function(){
return jq.each(function(){});
},
foo2: function(){
return jq.each(function(){});
}
}
};
})(jQuery);
Ответ 2
Я знаю, что почти на три года опаздываю на вечеринку, но, надеюсь, будущие читатели этого вопроса могут извлечь выгоду из моего ответа. Ответ GSto отлично смотрится с точки зрения дизайна плагина jQuery, но имеет одну небольшую проблему: вызов mynamespace()
clobbers возвращает экземпляр jQuery с новыми методами. Вот пример того, что это проблема:
$myDiv = $('.mydiv');
$myDiv.mynamespace().height(); // this will be `height' from mynamespace
$myDiv.height(); // this will STILL be `height' from mynamespace
// because it has overwritten $myDiv.height
Выбранный ответ не имеет этой проблемы, потому что amtec()
не является экземпляром jQuery и вместо этого является объектом, который вызывает его методы с экземпляром jQuery в качестве контекста. Я взял понятия из обоих ответов и написал плагин пространства имен ниже:
(function($) {
$.namespace = function(namespaceName, closures) {
if ($.fn[namespaceName] === undefined) {
$.fn[namespaceName] = function executor(context) {
if (this instanceof executor) {
this.__context__ = context;
}
else {
return new executor(this);
}
};
}
$.each(closures, function(closureName, closure) {
$.fn[namespaceName].prototype[closureName] = function() {
return closure.apply(this.__context__, arguments);
};
});
};
})(jQuery);
Пример использования:
$.namespace('milosz', {
redify: function() {
$(this).css('color', '#ff0000');
},
greenify: function() {
$(this).css('color', '#00ff00');
}
});
$.namespace('milosz', {
blueify: function() {
$(this).css('color', '#0000ff');
}
});
$('.mydiv').milosz().redify(); // The HTML elements with class `mydiv' are now red
В коде используются некоторые довольно низкоуровневые детали JavaScript, которые хорошо объясняются John Resig Advanced JavaScript tutorial, но свободно говорят, что происходит в следующем примере:
Когда вызывается milosz
(внутренне $.fn[namespaceName]
), this
указывает на экземпляр jQuery
, возвращаемый $('.mydiv')
. Следовательно, оператор if
попадает в блок else
, и конструктор версии milosz
вызывается (называется внутренним как executor
по причинам, которые должны стать очевидными). Конструктор передается одним параметром: this
, указатель на jQuery
экземпляр, который будет контекстом выполнения для всех членов пространства имен milosz
. Мы вернемся в оператор if
, на этот раз выполнив первый блок, где экземпляр прошедшего jQuery
хранится в переменной-члене под названием __context__
(которая, мы надеемся, имеет низкую вероятность перезаписывания). Возвращаемый объект возвращается со ссылкой на исходный экземпляр jQuery
и любые обертки, добавленные в его прототип путем вызова $.namespace
. Эти оболочки просто выполняют методы, переданные в пространство имен milosz
с исходным объектом jQuery
в качестве контекста, как это происходит при выполнении redify
.
Ба, я знаю, что это глоток, так или иначе, он работает как принятый ответ, но выглядит как ответ jQueryish, который для меня является лучшим из обоих миров.
Ответ 3
(function($){
$.namespace = function(ns, functions){
$.fn[ns] = function() {return this.extend(functions)};
};
$.namespace('$', $.fn); // the default namespace
})(jQuery);
Итак, теперь у вас есть плагин:
$.fn.func = function(){alert('plugin'); return this'};
и создавать плагины в пространстве имен:
$.namespace ('mynamespace', {
func: function() {alert('namespaced plugin'); return this;},
otherfunc: function() {return this.css('color', 'yellow');}
});
И если вы делаете
$('div').func(); // alerts 'plugin' -- no namespace
Но
$('div').mynamespace().func(); // alerts 'namespaced plugin'
и
$('div').mynamespace().func().$().func(); // alerts 'namespaced
plugin ', затем сбрасывается в нормальный jquery и плагин предупреждений
Ответ 4
Я знаю, это старый вопрос... Но зачем писать весь этот дополнительный код, когда вы можете просто заменить .
на _
?
$.fn.amtec_foo1 = function(){ return this.each(function(){}); }
$.fn.amtec_foo2 = function(){ return this.each(function(){}); }
Еще лучше, дайте плагину имя, которое оригинально и агностически для проекта.
$.fn.fooize = function(){ return this.html('Element has been Fooized!'); }
Ответ 5
$.cg = {
foo1: function(weq){
return console.log(weq);
},
foo2: function(rw){
return console.log(rw);
}
};
$.cg = { // will result in error because $.cg is already declared above
foo4: function(rw){ // will result in error
return console.log(rw); // will result in error
} // will result in error
}; // will result in error
$.cg.foo3 = function(weq){ //to add anything new to $.cg , you have to do it this way.
return console.log(weq);
}
$.cg.foo1("12");
$.cg.foo2("22"); //works fine.
$.cg.foo3("112"); //works fine.