问题
Suffice it to say, I'm wanting to branch my plugin writing a bit, and decided I want to be able to "namespace" them. So far, rewriting the $.method
ones to $.namespace.method
has been easy.
The problem I'm having is making Element Methods such as $('element').method()
, but to use a namespace; for example $('element').namespace.method()
. I've tried a few workarounds and can create $.fn.namespace.method
, however, when I call this
from within that method, I only get $.fn.namespace
and not the 'element'
that I'd like to get.
Example: If i call $('body').namespace.test()
, then inside method test
, I want this
to be the element <body></body>
Any help figuring out how to pull this off much appreciated. Probably just over-thinking things as usual.
Currently trying possible work-arounds for something like $('body').namespace().method()
, thus far, not working so well ... :P
回答1:
If you don't need to be compatible with IE8, you may use Object.defineProperty.
Working example :
Object.defineProperty($.fn, 'namespace', {
get: function(){
var t = this;
return {
lowercasehtml: function(){
return t.html(function(_,h){ return h.toLowerCase() });
}
}
}
});
$('#a').namespace.lowercasehtml(); // changes the html of #a to lowercase (yes, it's stupid, I know)
Demonstration
But I'm not convinced it's a good idea to namespace like this. I would have simply defined
$.fn.namespace_lowercasehtml = function() ...
That's what I personally do for my application specific extensions to jQuery.
回答2:
While I don't recommend it, you can generate a new object for every call to namespace()
:
(function($){
var plugin = {
test: function (){
console.log(this);
}
};
var methods = Object.keys( plugin );
$.fn.namespace = function (){
var self = this,
localMethods = {};
$.each(methods, function () {
localMethods[ this ] = plugin[ this ].bind(self);
});
return localMethods;
};
}(jQuery));
Here's the fiddle: http://jsfiddle.net/WaXzL/
You can either polyfill Object.keys for older browsers, or just create the methods
array manually.
Same goes for bind
: either polyfill it, or call
it manually.
Here's a version that would work in older browsers:
(function($){
var plugin = {
test: function (){
console.log(this);
}
};
var methods = [];
for ( var i in plugin ) {
if ( plugin.hasOwnProperty(i) ) {
methods.push(i);
}
}
$.fn.namespace = function (){
var self = this,
localMethods = {};
$.each(methods, function (i, method) {
localMethods[ method ] = function () {
plugin[ method ].call( self );
};
});
return localMethods;
};
}(jQuery));
And here's the fiddle: http://jsfiddle.net/WaXzL/1/
回答3:
How about instead of doing:
$('element').namespace.method()
you simplify it and do
$('element').namespace('method')
instead? This is much simpler:
(function($){
var methods = {
test: function(a, b){
console.log(this, a, b);
}
};
$.fn.namespace = function(method){
var params = Array.prototype.slice.call(arguments, 1);
return methods[method].apply(this, params);
};
}(jQuery));
Then you'd do something like: $('body').namespace('test', 1, 2);
回答4:
A better solution is to just have one main method, and pass the method name as a string:
(function($){
var plugin = {
test: function (){
console.log(this);
},
otherTest: function (){
console.log(this);
}
};
$.fn.namespace = function (method){
var args = Array.prototype.slice.call(arguments, 1);
return plugin[ method ].call(this, args);
};
}(jQuery));
Here's the fiddle: http://jsfiddle.net/yYNDH/
来源:https://stackoverflow.com/questions/17704130/how-to-create-jquery-element-methods-with-namespace