最近开发一个前端图表模块,使用jQuery和Highchart开发,然后提供给其他人用,发现调用时要写太多代码,能不能一行搞定。之前开发过几个jQuery扩展,于是也做成jQuery扩展,调用时类似$(‘#chart’).warning(options)这样子,简洁了不少。
jQuery扩展有两种,一种是$(‘#element’).func(),使用了选择器,定义是:
(function($) { //Plugin fucntions $.fn.PluginName = function(options) { // Plugin initial } })(jQuery);
将PluginName这个插件注册到$.fn上面,另外一种$.func(options),不绑定元素的,定义是:
(function($) { //Plugin fucntions $.PluginName = function(options) { // Plugin initial } })(jQuery);
将PluginName直接挂在了$对象下面。
jQeury.extend方法可以用来扩展对象,也可以用来增加插件:
//$('#el').PluginName方式 jQuery.fn.extend({ PluginName: function(options) { // Plugin initial } }); //对原有的PluginName插件再进一步扩展,也可用于升级插件而不修改原有代码 jQuery.fn.PluginName.extend({ doSomething: function(options) { // Plugin extend } }); jQuery.extend(true, jQuery.fn.PluginName.prototype, {}); //$.PluginName方式 jQuery.extend({ PluginName: function(options) { // Plugin initial } }); jQuery.PluginName.extend({ doSomething: function(options) { // Plugin extend } });
以下是一个简单的jQuery插件模板,来自这里:
/* * Project: * Description: * Author: * License: */ // 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 ) { // 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 your plugin). // Create the defaults once var pluginName = 'defaultPluginName', defaults = { propertyName: "value" }; // The actual plugin constructor function Plugin( element, options ) { this.element = 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.options = $.extend( {}, defaults, options) ; this._defaults = defaults; this._name = pluginName; this.init(); } Plugin.prototype.init = function () { // Place initialization logic here // You already have access to the DOM element and the options via the instance, // e.g., this.element and this.options }; // You don't need to change something below: // 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. $(element).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 element 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') { // Cache the method call // to make it possible // to return a value var returns; this.each(function () { var instance = $.data(this, 'plugin_' + pluginName); // Tests that there's already a plugin-instance // and checks that the requested public method exists if (instance instanceof Plugin && typeof instance[options] === 'function') { // Call the method of our plugin instance, // and pass it the supplied arguments. returns = instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) ); } // Allow instances to be destroyed via the 'destroy' method if (options === 'destroy') { $.data(this, 'plugin_' + pluginName, null); } }); // If the earlier cached method // gives a value back return the value, // otherwise return this to preserve chainability. return returns !== undefined ? returns : this; } }; }(jQuery, window, document));
根据这个就可以方便的开发jQuery插件了。
也可以使用jQuery.widget来开发一个插件,参考这里:
//新插件 $.widget( "custom.superDialog", {} ); //继承原有jQuery UI插件 $.widget( "custom.superDialog", $.ui.dialog, {} );
除此之外,也可以自己写插件/模块:
(function () { // 将插件/模块定义在闭包私有空间里,加载时候就会立即执行,初始化 this.PluginName = function(options) { } PluginName.prototype.doSomething = function(options) { } }());
然后就可以调用了
var plugin = new PluginName(options); plugin.doSomething();
也可以这样子:
var MODULE = (function (my) { my.moduleMethod = function () { // method override, has access to old through old_moduleMethod... }; return my; }(MODULE || {})); #子模块,挂在MODULE这个对象/命名空间下面 MODULE.sub = (function () { var my = {}; // ... return my; }());
模块多了就需要模块管理工具了,比如RequireJS:
//定义 define('myModule', ['foo', 'bar'], // module definition function // dependencies (foo and bar) are mapped to function parameters function ( foo, bar ) { // return a value that defines the module export // (i.e the functionality we want to expose for consumption) // create your module here var myModule = { doStuff:function(){ console.log('Yay! Stuff'); } } return myModule; }); #使用 require(['app/myModule'], function( myModule ){ // start the main module which in-turn // loads other modules var module = new myModule(); module.doStuff(); });
Javascript模块话加载可以参考这里。
参考链接:
JavaScript Module Pattern: In-Depth
Advanced Plugin Concepts
Learning JavaScript Design Patterns
jQuery Plugin Pattern
理解jquery的$.extend()、$.fn和$.fn.extend()
Making Use of jQuery UI’s Widget Factory
Building Your Own JavaScript Modal Plugin
Writing Modular JavaScript With AMD, CommonJS & ES Harmony
Javascript文件加载:LABjs和RequireJS
jQuery Boilerplate——流行的jQuery插件开发模板