1.jQuery插件的命名方式:jquery.[插件名].js
2.对象方法附加在jQuery.fn上,全局函数附加在jQuery对象本身上
3.插件内部this指向的是通过选择器获取的jQuery对象
4.结尾加分号,插件头部最好也加分号
5.插件应该返回一个jQuery对象,保证插件的链式操作
6.插件内部应用完整的jQuery而不是$,但可以利用闭包,将jQuery传入,使插件内部可以继续使用$符合作为jQuery别名
7.闭包另一大好处:可以避免内部变量影响全局空间
;(function($){ })(jQuery);//jQuery作为实参传递给$
红色的()代表运算符,执行绿色的括号()
8.jQuery.extend()方法:扩展jQuery对象、扩展已有的object对象
9.jQuery.extend()方法常用于设置插件方法的一系列默认参数,可以很方便的用传入的参数来覆盖默认值。
10.jQuery的选择符可能会匹配一个或多个元素,所以写插件时,可以用each()方法遍历元素,然后执行相应的方法,this.each(。。)this会依次引用每个DOM元素
采用UMD: 通用模块规范:
参考:http://web.jobbole.com/82238/
既然CommonJs和AMD风格一样流行,似乎缺少一个统一的规范。所以人们产生了这样的需求,希望有支持两种风格的“通用”模式,于是通用模块规范(UMD)诞生了。不得不承认,这个模式略难看,但是它兼容了AMD和CommonJS,同时还支持老式的“全局”变量规范:
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之类的 module.exports = factory(require('jquery')); } else { // 浏览器全局变量(root 即 window) root.returnExports = factory(root.jQuery); } }(this, function ($) { // 方法 function myFunc(){}; // 暴露公共方法 return myFunc; }));
接下来结合注释分析jQuery手风琴插件:
;(function (factory) { if (typeof define === "function" && (define.amd || define.cmd) && !jQuery) { // AMD或CMD define([ "jquery" ],factory); } else if (typeof module === 'object' && module.exports) { // Node/CommonJS module.exports = function( root, jQuery ) { if ( jQuery === undefined ) { if ( typeof window !== 'undefined' ) { jQuery = require('jquery'); } else { jQuery = require('jquery')(root); } } factory(jQuery);//将jQuery作为实参传递给factory函数,在factory中就可以使用$符号了 return jQuery; }; } else { //Browser globals factory(jQuery); } }(function ($) {//function(factory){。。。}(function($){xxx})立即执行, //function($){xxx}这个函数将作为参数传递给factory,不直接写在里面,是因为要兼容不同的模式,提高代码复用性,否则得写三次 //function(factory){}(),这个()是运算符,执行这个函数 , //利用闭包(函数中的函数),可以继续使用$符号 $.fn.accordion = function(parameter,getApi) {//对象方法要附加到jQuery.fn对象上 if(typeof parameter == 'function'){ //重载 getApi = parameter; parameter = {};//只传入了一个参数,且这个参数对应的是getApi }else{ parameter = parameter || {};//传入两个参数的情形 getApi = getApi||function(){}; } var defaults = { triggerCls: "trigger", //主列表的class值 panelCls: "panel", //列表所对应的内容列表的class值 activeCls: "active", //导航选中时的class triggerType: 'mouse', //切换时的触发事件 activeIndex: 0, //默认选中导航项的索引 multiple: false, //是否同时支持多面板展开 animate: false, //是否开启动画 duration:500, //动画开启时长 beforeEvent: function() { //切换前执行,返回flase时不移动;传入一个对象,包含:target当前导航项对象,tabs导航列表对象,panels内容列表对象,index当前导航项索引,event事件对象; }, afterEvent: function() { //切换后执行;传入一个对象,包含:target当前导航项对象,tabs导航列表对象,panels内容列表对象,index当前导航项索引,event事件对象; } }; var options = $.extend({}, defaults, parameter);//jQuery除了可以扩展jQuery对象外,还可以扩展object对象 //用defaults, parameter对象扩展{} //结果是options合并了这两个对象 //$.extend()经常用于设置插件方法的一系列默认参数 //这里defaults就是默认参数,parameter是传递的参数,传递的参数会覆盖默认参数 return this.each(function() {//调用each()遍历选中的元素,且返回jQuery对象 //对象定义 var $this = $(this); var $triggers = $this.find("." + options.triggerCls); var $panels = $this.find("." + options.panelCls); //全局变量 var _api = {}; options.triggerType += options.triggerType === "mouse" ? "enter" : ""; //使用mouseenter防止事件冒泡,先执行=== //函数 _api.select = function(i,animate){ var animate = animate==false?animate:options.animate; if(options.multiple){ if(animate){ $panels.eq(i).slideToggle(options.duration); }else{ $panels.eq(i).toggle(options.duration); } $triggers.eq(i).toggleClass(options.activeCls); }else{ if(animate){ $panels.not(':eq('+i+')').slideUp(options.duration); $panels.eq(i).slideDown(options.duration); }else{ $panels.not(':eq('+i+')').hide(); $panels.eq(i).show(); } $triggers.removeClass(options.activeCls).eq(i).addClass(options.activeCls); } }; //初始化 _api.select(options.activeIndex,false); $triggers.bind(options.triggerType, function(e) { //事件绑定 var i = $triggers.index($(this)); var status = { target:$this, triggers:$triggers, panels:$panels, index:i, event:e }; if(options.beforeEvent(status)!=false){ _api.select(i); options.afterEvent(status); } }); getApi(_api); }); }; }));