解读jQuery插件开发流程
Word文档解读jQuery插件开发流程 jQuery库中包括许多函数,所以开发插件的时候往往就需要留意命名空间和私有作用域等方面,下面就由Shawn Khameneh老司机带你解读jQuery插件开发流程及相关留意点. jquery插件开发模式 jquery插件一般有三种开发方式: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget()应用jQuery UI的部件工厂方式创建 第一种$.extend()相对简洁,一般很少能够独立开发冗杂插件,第三种是一种高级的开发模式,本文也不做介绍。第二种则是一般插件开发用到的方式,本文着重讲讲第二种。 插件开发 第二种插件开发方式一般是如下定义 $.fn.pluginName = function() /your code here 插件开发,我们一般运用面向对象的思维方式 例如定义一个对象 var Haorooms= function(el, opt) this.$element = el, this.defaults = color: red, fontSize: 12px, textDecoration:none , this.options = $.extend(, this.defaults, opt) /定义haorooms的方法 haorooms.prototype = changecss: function() return this.$element.css( color: this.options.color, fontSize: this.options.fontSize, textDecoration: this.options.textDecoration ); $.extend(, this.defaults, opt)有主要是为了创建一个新对象,保存对象的默认值。 $.fn.myPlugin = function(options) /创建haorooms的实体 var haorooms= new Haorooms(this, options); /调用其方法 return Haorooms.changecss(); 调用这个插件直接如下就可以 $(function() $(a).myPlugin( color: #2C9929, fontSize: 20px ); ) 上述开发方法的问题 上面的开发方法存在一个严重的问题,就是定义了一个全局的Haorooms,这样对于插件的兼容等等各个方面都不好。万一别的地方用到了Haorooms,那么你的代码就悲催了!如今我们把上面的代码包装起来,用一个自调用匿名函数(有时又叫块级作用域或者私有作用域)包裹,就不会出现这个问题了!包括js插件的开发,也是一样的,我们用一个自调用匿名函数把自己写的代码包裹起来,就可以了!包裹方法如下: (function() )() 用上面的这个包裹起来,就可以了。 但是还有一个问题,当我们讨论大牛的代码的时候,前面常常看到有“;”,那是为了避开代码合并等不必要的错误。 例如,我们随便定义一个函数: var haoroomsblog=function() (function() )() 由于haoroomsblog这个函数后面没有加分号,导致代码出错,为了避开这类状况的发生,通常这么写! ;(function() )() 把你的插件代码包裹在上面里面,就是一个简洁的插件了。注js插件和jquery插件都是如此 还有一个问题 把你的插件包裹在 ;(function() )() 基本上可以说是完善了。但是为了让你开发的插件应用更加广泛,兼容性更加好,还要考虑到用插件的人的一些特别的做法,例如,有些伴侣为了避开jquery和zeptojs冲突,将jquery的前缀“$”,修改为“jQuery”,还有些伴侣将默认的document等方法修改。为了让你的插件在这些东西修了了的状况下照常运行,那么我们的做法是,把代码包裹在如下里面: ;(function($,window,document,undefined) /我们的代码。 )(jQuery,window,document); 就可以避开上面的一些状况了! 优秀的示例 下面,我们有了一个插件的基本层次: (function($) var privateFunction = function() / 代码在这里运行 var methods = init: function(options) return this.each(function() var $this = $(this); var settings = $this.data(pluginName); if(typeof(settings) = undefined) var defaults = propertyName: value, onSomeEvent: function() settings = $.extend(, defaults, options); $this.data(pluginName, settings); else settings = $.extend(, settings, options); / 代码在这里运行 ); , destroy: function(options) return $(this).each(function() var $this = $(this); $this.removeData(pluginName); ); , val: function(options) var someValue = this.eq(0).html(); return someValue; ; $.fn.pluginName = function() var method = arguments0; if(methodsmethod) method = methodsmethod; arguments = Array.prototype.slice.call(arguments, 1); else if( typeof(method) = object | !method ) method = methods.init; else $.error( Method + method + does not exist on jQuery.pluginName ); return this; return method.apply(this, arguments); )(jQuery); 你可能会留意到,我所提到代码的结构和其他插件代码有很大的不同。依据你的使用和需求的不同,插件的开发方式也可能会呈现多样化。我的目的是澄清代码中的一些概念,足够让你找到适合自己的方法去理解和开发一个jQuery插件。 如今,来解剖我们的代码吧! 容器:一个即时执行函数 根本上来说,每个插件的代码是被包含在一个即时执行的函数当中,如下: (function(arg1, arg2) / 代码 )(arg1, arg2); 即时执行函数,顾名思义,是一个函数。让它别出心裁的是,它被包含在一对小括号里面,这让全部的代码都在匿名函数的局部作用域中运行。这并不是说DOM全局变量在函数内是被屏蔽的,而是外部无法访问到函数内部的公共变量和对象命名空间。这是一个很好的开始,这样你声明你的变量和对象的时候,就不用担忧着变量名和已经存在的代码有冲突。 如今,因为函数内部全部的全部公共变量是无法访问的,这样要把jQuery本身作为一个内部的公共变量来使用就会成为问题。就像一般的函数一样,即时函数也依据引用传入对象参数。我们可以将jQuery对象传入函数,如下: (function($) / 局部作用域中使用$来引用jQuery )(jQuery); 我们传入了一个把公共变量“jQuery”传入了一个即时执行的函数里面,在函数局部容器中我们可以通过“$”来引用它。也就是说,我们把容器当做一个函数来调用,而这个函数的参数就是jQuery。因为我们引用的“jQuery”作为公共变量传入,而不是它的简写“$”,这样我们就可以兼容Prototype库。假如你不用Prototype或者其它用“$”做简写的库的话,你不这样做也不会造成什么影响,但是知道这种用法仍是一件好事。 插件:一个函数 一个jQuery插件本质上是我们塞进jQuery命名空间中一个浩大的函数,当然,我们可以很轻易地用“jQuery.pluginName=function”,来到达我们的目的,但是假如我们这样做的话我们的插件的代码是处于没有被爱护的暴露状态的。“jQuery.fn”是“jQuery.prototype”的简写,意味当我们通过jQuery命名空间去获取我们的插件的时候,它仅可写不行修改。它事实上可以为你干点什么事呢?它让你恰当地组织自己的代码,和理解如何爱护你的代码不受运行时候不需要的修改。最好的说法就是,这是一个很好的实践! 通过一个插件,我们获得一个基本的jQuery函数: (function($) $.fn.pluginName = function(options) / 代码在此处运行 return this; )(jQuery); 上面的代码中的函数可以像其他的jQuery函数那样通过“$(#element).pluginName()”来调用。留意,我是如何把“return this”语句加进去的;这小片的代码通过返回一个原来元素的集合包含在this当中的引用来产生链式调用的效果,而这些元素是被一个jQuery对象所包裹的。你也应当留意,“this”在这个特定的作用域中是一个jQuery对象,相当于“$(#element)”。 依据返回的对象,我们可以总结出,在上面的代码中,使用“$(#element).pluginName()”的效果和使用“$(#element)”的效果是一样