编写插件的目的:给已经有的一系列方法或函数做一个封装,以便在其他地方重复使用,方便后期维护和提高开发效率。
jQuery插件类型
jQuery插件主要分为3种类型:
1.封装对象方法的插件(对象级别组件开发)
这种插件是将对象方法封装起来,用于对通过选择器获取的jquery对象进行操作,是最常见的一种插件。这类插件可以发挥出jQuery选择器的强大优势。
即挂在jQuery原型下的方法,这样通过选择器获取的jQuery对象实例也能共享该方法,也称为动态方法(实例方法)
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
2.封装全局函数的插件(类级别组件开发)
可以将独立的函数加到jQuery命名空间之下,例如jQuery.noConflict()方法就是jQuery内部作为全局函数的插件附加到内核上去的。
即给jQuery命名空间下添加新的全局函数,也称为静态方法
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
3.选择器插件
个别情况下,会需要用到选择器插件。
插件的基本要点
- jQuery插件的文件名推荐命名为jQuery.[插件名].js,以免和其他JavaScript库插件混淆。
- 所有的对象方法都应该附加到jQuery.fn对象上,而所有的全局函数都应该附加到jQuery对象本身上
- 在插件内部,this指向的是当前通过选择器获取到的jQuery对象。
- 可以通过this.each来遍历所有元素
- 所有的方法或函数插件,都应当以分号结尾,否则压缩的时候可能出现问题。为了更加稳妥些,甚至可以在插件头部先加上一个分号,以免他人的不规范代码给插件带来影响。
- 插件应该返回一个jQuery对象,以保证插件的可链式操作。
常见插件形式
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
插件开头不加分号的问题
举个例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
特别说明: 由上面的例子可以看出,在插件前加分号还是很有必要的。
插件中的闭包
关于闭包,ECMAScript对其进行了这样的定义:允许使用内部函数(即函数定义和函数表达式位于另一个函数的函数体内),而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数,当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。即内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它让然必须访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明的值是外部函数返回时的值,但也会受到内部函数的影响。
我们利用闭包可以访问和修改包含函数中的局部变量
利用闭包的特性,既可以避免内部临时变量影响全局空间,又可以在插件内部继续使用$作为jQuery的别名.
提供插件的默认选项
插件应该会有一些选项是可以让开发者自己根据需要设置的,所以提供恢复默认选项是以有必要的。你可以通过jQuery的extend功能来设置这些选项:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
jQuery提供了两个用于扩展jQuery功能的方法:jQuery.extend()和jQuery.fn.extend().这两个方法都接受一个参数,类型为Object。Object对象的”名/值对”分别代表”函数或方法名/函数主体”.
特别说明: $.extend()方法的第一个参数是一个空对象,而不是默认参数defaults,这里的原因是为了保护默认参数值不会被用户自定义参数所修改。
jQuery.extend()用法
jQuery.extend()方法除了可以用于扩展jQuery对象外,还可以用于扩展已有的object对象。
将对象的属性添加给jQuery对象
Demo:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
用一个或多个其他对象来扩展一个对象,然后返回被扩展的对象。
Demo:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
浅拷贝:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
深拷贝:也会对嵌套子对象进行递归合并
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
深拷贝和浅拷贝结果对比:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
浅拷贝的结果直接将banana的值进行了替换,深拷贝对banana的值进行合并修改,不是简单的直接替换。
jQuery.extend()方法经常被用于设置插件方法的一系列默认参数
Demo:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
我们在调用fn()方法的时候,在传递的参数options对象中设置了相应的值,那么就使用设置的值,否则就使用默认值。通过使用$.extend()方法,可以很方便地用传入的参数来覆盖默认值。
jQuery插件编写
jQuery.color插件
- 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
- 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
jQuery.color.js
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
面向对象的插件开发
这里有一个疑问:为什么要有面向对象的方式来开发插件?为了解决这个问题,也查了很多资料,最后明白原因。
因为如果不这样,你可能需要一个方法的时候就去定义一个function,当需要另外一个方法的时候,再去随便定义一个function,同样,需要一个变量的时候,毫无规则地定义一些散落在代码各处的变量。
还是老问题,不方便维护,也不够清晰。当然,这些问题在代码规模较小时是体现不出来的。
如果将需要的重要变量定义到对象的属性上,函数变成对象的方法,当我们需要的时候通过对象来获取,一来方便管理,二来不会影响外部命名空间,因为所有这些变量名还有方法名都是在对象内部。
采用面向对象的方式开发,有利于更好地维护和理解插件,以后要加新功能新方法,只需向对象添加新变量及方法即可,然后在插件里实例化后即可调用新添加的东西。
Demo:
- 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
- 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
防止全局变量污染
不仅仅是jQuery插件的开发中需要注意这个问题,我们在写任何JS代码时都应该注意的一点是不要污染全局变量。随着代码量的增多,如果有意无意在全局范围内定义一些变量的话,最后很难维护,也容易跟别人写的代码有冲突。
举个例子:你在代码中向全局window对象添加了一个变量status用于存放状态,同时页面中引用了另一个别人写的库,也向全局添加了这样一个同名变量,最后的结果肯定不是你想要的。所以不到万不得已,一般我们不会将变量定义成全局的。
解决方法:使用自执行的匿名函数包裹插件代码,这样就可以完全放心,安全地将它用于任何地方了,绝对没有冲突。我们知道JavaScript中无法用花括号方便地创建作用域,但函数却可以形成私有作用域,域内的代码是无法被外界访问的。如果我们将自己的代码放入一个函数中,那么就不会污染全局命名空间,同时不会和别的代码冲突。
- 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
- 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
这样写还有一个好处就是:自调用匿名函数里面的代码会在第一时间执行,页面准备好过后,上面的代码就将插件准备好了,以方便在后面的代码中使用插件。
在上面的代码中还要注意一点:我们将jQuery对象、window对象以及undefined作为实参传递给了匿名函数。
这样window等系统变量在插件内部就有了一个局部的引用,可以提高其访问速度,有助于性能的提升(我们都知道:全局变量的查找是最慢的)。
参考博文:
创建更好jQuery插件的10个建议
jQuery插件开发模式
深入理解jQuery插件开发