我目前正忙于基于样板设置jQuery插件,但是我似乎无法通过直接调用从外部访问函数,例如:
var myPlugin = $("#container").myPlugin();
myPlugin.someFunction(); // This does not work
$("#container").myPlugin("someFunction") // This works
链接当前如下所示:
$("#container").myPlugin("chainMethod").myPlugin("chainMethod2");
我希望它看起来像这样:
var myPlugin = $("#container").myPlugin();
myPlugin.chainMethod().chainMethod2();
我认为解决第一个问题也会自动解决第二个问题,但是我不知道自己在做什么错。任何解决我的问题的帮助都将受到赞赏。
我的插件代码(带有注释)定义如下:
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ($, window, document, undefined) {
"use strict";
// undefined is used here as the undefined global variable in ECMAScript 3 is mutable (ie. it can be changed
// by someone else). undefined isn't really being passed in so we can ensure the value of it is truly undefined.
// In ES5, undefined can no longer be modified.
// window is passed through as local variable rather than global as this (slightly) quickens the resolution
// process and can be more efficiently minified (especially when both are regularly referenced in a plugin).
// Create the defaults once
var pluginName = 'myPlugin',
defaults = {
id: 0,
propertyName: "value"
};
// The actual plugin constructor
function Plugin(element, options) {
this.elem = element;
this.$elem = $(element);
// jQuery has an extend method which merges the contents of two or more objects, storing the result
// in the first object. The first object is generally empty as we don't want to alter the default
// options for future instances of the plugin
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function () {
// Place initialization logic here. You already have access to the DOM el and
// the options via the instance, e.g. this.el and this.settings
this.$elem.text("jQuery Boilerplate");
this._somePrivateFunc();
},
destroy: function () {
$.data(this, 'plugin_' + pluginName, null);
},
someFunction: function () {
console.log("someFunction");
},
_somePrivateFunc: function () {
console.log("Private Func");
},
someGetterMethod: function () {
return "This is a getter method";
},
chainMethod: function() {
console.log("Chain");
return this;
},
chainMethod2: function() {
console.log("Chain 2");
return this;
}
});
// A really lightweight plugin wrapper around the constructor, preventing against multiple instantiations and
// allowing any public function (ie. a function whose name doesn't start with an underscore) to be called
// via the jQuery plugin, e.g. $(el).defaultPluginName('functionName', arg1, arg2)
$.fn[pluginName] = function (options) {
var args = arguments;
// Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
if (options === undefined || typeof options === 'object') {
return this.each(function () {
// Only allow the plugin to be instantiated once, so we check that the el has no
// plugin instantiation yet
if (!$.data(this, 'plugin_' + pluginName)) {
// if it has no instance, create a new one, pass options to our plugin constructor,
// and store the plugin instance in the elements jQuery data object.
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
// If the first parameter is a string and it doesn't start with an underscore or "contains" the
// `init`-function, treat this as a call to a public method.
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
// Call a public plugin method (not starting with an underscore) for each selected element.
if (Array.prototype.slice.call(args, 1).length == 0 && $.inArray(options, $.fn[pluginName].getters) != -1) {
// If the user does not pass any arguments and the method allows to work as a getter then
// break the chainability so we can return a value instead the element reference.
var instance = $.data(this[0], 'plugin_' + pluginName);
return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
} else {
// Invoke the specified method on each selected element
return this.each(function () {
var instance = $.data(this, 'plugin_' + pluginName);
if (instance instanceof Plugin && typeof instance[options] === 'function') {
instance[options].apply(instance, Array.prototype.slice.call(args, 1));
}
});
}
}
};
// Names of the plugin methods that can act as a getter method.
$.fn[pluginName].getters = ['someGetterMethod'];
}(jQuery, window, document));
谢谢。