我一直在尝试学习如何构建 jQuery 插件,所以我还是新手。由于这是我的第一个插件,我决定尝试一个简单的可折叠面板/盒子(你只能阅读这么多,对吧?)。当点击事件触发时,我无法访问对我的 Javascript 类对象的引用。我知道事件内部的 this 是指触发事件的元素。我也知道我可以_self = this;
在事件之前做一些事情,但这只会缓存集合中的最后一个对象。有人对我如何保留对类对象的引用有任何建议吗?
谢谢!
这是我的代码。
HTML 代码
<div class="mypanel" title="Panel 1">Testing panel 1</div>
<div class="mypanel" title="Panel 2">Testing panel 2</div>
$('.mypanel').collapsiblePanel();
插件代码
var contentVisible = 'showContent', contentNotVisible = 'hideContent';
;(function($) {
var pluginName = 'collapsibleBox';
function Plugin(element, options) {
this.ele = element;
this.$ele = $(element);
var _self = this;
this.options = $.extend({}, $.fn[pluginName].defaults, options);
this.init();
/* Expose methods of Plugin we wish to be public.
* This gets stored when the plugin is created
*/
return {
option: this.option,
destroy: this.destroy
/* Other public methods here */
}
}
$.fn[pluginName] = function(options) {
/* If the first parameter is a string, treat this as a call to a public method. */
if(typeof arguments[0] === 'string') {
var methodName = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
var returnVal;
this.each(function() {
/* Check that the element has a plugin instance, and that
* the requrested public method exists.
*/
if($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
/* Call the method of the Plugin instance, and Pass it the supplied arguments */
returnVal = $.data(this, 'plugin_' + pluginName)[methodName].appy(this, args);
}
else {
$.error('Method ' + methodName + ' does not exist on jQuery.' + pluginName);
}
});
if(returnVal !== undefined) {
/* If the method returned something, return it */
return returnVal;
}
else {
/* Otherwise, returning 'this' preserves chainability */
return this;
}
}
/* If the first parameter is an object (options), or was omitted,
* instantiate a new instance of the plugin
*/
else if(typeof options === 'object' || !options) {
return this.each(function() {
/* Only allow the plugin to be instantiated once */
if(!$.data(this, 'plugin_' + pluginName)) {
/* Pass options to Plugin constructor, and store Plugin
* instance in the element's jQuery data object
*/
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
}
};
$.fn[pluginName].defaults = {
onInit: function() {},
onDestroy: function() {}
};
Plugin.prototype = {
init: function() {
this.createContentArea();
this.createTitleBar();
this.hook('onInit');
},
createContentArea: function() {
/* ... */
},
createTitleBar: function() {
/* ... */
this.$title.click(function() {
if(this.$ele.data('state') == contentVisible) { // The problem is here
this.collapse();
}
else {
this.expand();
}
});
},
expand: function() {
this.$content.slideDown();
this.$ele.data('state', contentVisible);
},
collapse: function() {
console.log(this);
this.$content.slideUp();
this.$ele.data('state', contentNotVisible);
},
/* Use this function to get/set variables */
option: function (key, val) {
if(val) {
this.options[key] = val;
}
else {
return this.options[key];
}
},
destroy: function () {
/* ... */
},
hook: function (hookName) {
if(this.options[hookName] !== undefined) {
this.options[hookName].call(this.ele);
}
}
};
})(jQuery);