最近开发一个前端图表模块,使用jQuery和Highchart开发,然后提供给其他人用,发现调用时要写太多代码,能不能一行搞定。之前开发过几个jQuery扩展,于是也做成jQuery扩展,调用时类似$(‘#chart’).warning(options)这样子,简洁了不少。
jQuery扩展有两种,一种是$(‘#element’).func(),使用了选择器,定义是:
1 2 3 4 5 6 | ( function ($) { //Plugin fucntions $.fn.PluginName = function (options) { // Plugin initial } })(jQuery); |
将PluginName这个插件注册到$.fn上面,另外一种$.func(options),不绑定元素的,定义是:
1 2 3 4 5 6 | ( function ($) { //Plugin fucntions $.PluginName = function (options) { // Plugin initial } })(jQuery); |
将PluginName直接挂在了$对象下面。
jQeury.extend方法可以用来扩展对象,也可以用来增加插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | //$('#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插件模板,来自这里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | /* * 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来开发一个插件,参考这里:
1 2 3 4 | //新插件 $.widget( "custom.superDialog" , {} ); //继承原有jQuery UI插件 $.widget( "custom.superDialog" , $.ui.dialog, {} ); |
除此之外,也可以自己写插件/模块:
1 2 3 4 5 6 7 | ( function () { // 将插件/模块定义在闭包私有空间里,加载时候就会立即执行,初始化 this .PluginName = function (options) { } PluginName.prototype.doSomething = function (options) { } }()); |
然后就可以调用了
1 2 | var plugin = new PluginName(options); plugin.doSomething(); |
也可以这样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | //定义 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插件开发模板