我正在编写我的第一个jQuery插件。这是插件的骨架:
(function( $ ) {
var methods = {
init : function( options ) {
var settings = $.extend( {
'id' : '#' + this[0].id,
'foo' : 3,
'bar' : 4,
}, options );
}
}
$.fn.MyPlugin = function( method ) {
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 MyPlugin' );
}
};
})( jQuery );
我附上了这样的插件:
$( '#some-id' ).MyPlugin({
'something' : 'something
});
在一个页面上适用于一个控件,但是当我开始这样做时:
$( '#some-id-2' ).MyPlugin({
'something' : 'something
});
$( '#some-id-3' ).MyPlugin({
'something' : 'something
});
我收到以下错误:
Uncaught TypeError: Cannot read property 'id' of undefined
因为我从this
获取了我的ID,对于我目前所在页面上没有的任何控件,其评估结果为[]
。
获取插件附加控件的ID的正确方法是什么?
非常感谢:)。
答案 0 :(得分:11)
这里有一个根本问题:你在思考一个单独的元素。 jQuery完全是关于 sets 的元素。插件中的this
是一个jQuery实例,其中可能包含0..n
个匹配的元素。可能是零,一,27,342等。所以做this[0].id
在jQuery插件中没有意义,因为你只需得到第一个匹配元素的id
(如果它甚至有一个;没有必要的要求),或者当集合中根本没有任何元素时出现错误(如你所发现的那样)。
因此,如果您开始考虑将插件视为处理匹配元素的 set ,这些元素可能是空集,小集或大集,那么您将会在正确的道路。
这是一个具体的例子:让我们编写一个做傻事的插件:它将元素变成一种颜色,然后在超时后将它们恢复为原始颜色。我们将这样使用它:
$("selector").plugin("newcolor", timeout)
如果我们考虑单个元素,我们的插件将无法正常工作:
// The "foo" plug-in thinks in terms of just one element
$.fn.foo = function(color, time) {
var self, oldColor;
self = this;
// Save the current color -- this is wrong
oldColor = self.css("color");
// Set new color
self.css("color", color);
// Restore old color after timeout
setTimeout(function() {
self.css("color", oldColor);
}, time);
};
现在让我们使用它:
$("#theButton").click(function() {
$(".foo").foo("blue", 1000);
});
...使用此HTML:
<div class="foo">This is the first "foo" div</div>
<div class="foo" style="color: green">This is the second "foo" div</div>
<div class="foo" style="color: red">This is the third "foo" div</div>
<div><input type="button" id="theButton" value="Use foo"></div>
这里的问题是,通过考虑一个元素,插件错误地保存了第一个元素的颜色;当它“恢复”原始颜色时,它将第一个元素的颜色应用于所有其他颜色,这是错误的。我们最终得到三个使用黑色文本的div,其中第二个不应该是黑色。 Live example | Source
相反,如果我们按照集合来思考,我们会这样做(例如;不要说这是地球上最漂亮的代码):
// The "bar" plug-in understands sets
$.fn.bar = function(color, time) {
var self;
self = this;
// Get the current color of each element
self.each(function() {
var entry = $(this);
entry.data("oldColor", entry.css("color"));
});
// Set new color
self.css("color", color);
// Restore old color after timeout
setTimeout(function() {
self.each(function() {
var entry = $(this);
entry.css("color", entry.data("oldColor")).removeData("oldColor");
});
}, time);
};
我们会像这样使用它(基本相同):
$("#theButton").click(function() {
$(".bar").bar("blue", 1000);
});
...使用此HTML(基本相同):
<div class="bar">This is the first "bar" div</div>
<div class="bar" style="color: green">This is the second "bar" div</div>
<div class="bar" style="color: red">This is the third "bar" div</div>
<div><input type="button" id="theButton" value="Use foo"></div>
请注意它是如何通过data
保存每个元素的颜色以及元素本身的颜色。恢复时,它会恢复每个元素的颜色。 Live example | Source
答案 1 :(得分:1)
您应该使用each
实现插件,然后您就不会遇到空jQuery对象的问题:
$.fn.MyPlugin = function( method ) {
this.each(function() {
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 MyPlugin' );
}
});
};