插件实现方式
1、声明立即调用函数
+function($){"use strict",......}(jquery)
定义一个立即调用的函数声明,如代码清单2-1所示。在参数里传入jQuery对象,通过参数$引入变量
,这样其所有代码在使用jQuery的时候,直接使用$符即可。这样的做法,有以下两个好处:❑函数内部的$符变量代表了局部变量,而不是全局变量里代表jQuery的$符变量,以达到防止变量污染的目的。❑内部的代码全部都是私有代码,外部代码无法访问,只有通过第三步,在$.fn上设置了插件(比如$.fn.alert=)的形式,通过$符变量才能将整个插件通过唯一的接口$.fn.alert暴露出去,从而保护了其内部代码。
+function ($) {
"use strict";// 1.使用严格模式ES5支持
// 2.alert插件类及原型方法的定义
// 3.在jQuery上定义alert插件,并重设插件构造器
// 重设插件构造器,可以通过该属性获取插件的真实类函数
// 4. 防冲突处理
// 5. 绑定触发事件
}(window.jQuery);
注意:在function关键字前面有一个加号运算符(+),其主要目的是防止前面有未正常结束的代码(通常是遗漏了分号),导致前后代码被编译器认为是一体的,从而导致代码运行出错。
2、定义相关插件类及原型方法
例如:alert prototype.close
步骤2 定义该插件的核心代码,也就是在触发特定行为(通常是单击行为)后要进行处理的代码。插件核心代码示例// alert插件类及原型方法的定义// 定义选择器,所有符合该自定义属性的元素都可以触发下面的事件
var dismiss = '[data-dismiss="alert"]'var Alert = function (el) {
// 传入元素,如果元素内部有dismiss上设置的自定义属性,则click事件会触发原型上的
close方法
$(el).on('click', dismiss, this.close)
}
Alert.prototype.close = function (e) { // 关闭警告框的主要代码设置,每一行代码的细节注释,请参考5.8节}
通过上述代码可以看出,主要是先定义了插件插件的类函数Alert,然后再定义需要用到的一些原型函数,比如close函数方法。Alert函数接收el参数,el表示DOM元素,一个DOM如果绑定了data-dismiss="alert"自定义属性,则在单击的时候就会触发close函数方法,从而达到关闭的目的。同样,Modal插件也是先定义Modal类函数,然后再在Modal的原型上定义toggle和show等方法,其内部根据相应的规则再细化处理。
3、在jquery上定义插件,并重设插件构造函数
例如:$.fn.alert.Constructor=Alert
在jQuery上定义插件,以便通过jQuery.插件名称的方式,也能够使用该插件,也就是在触发特定行为(通常是单击行为)后要进行处理的通用代码。最后在这里再调用插件类或原型方法。主要源码如代码清单2-3所示。代码清单2-3jQuery插件定义// 在jQuery上定义alert插件,并重设插件构造器var old = $.fn.alert// 保留其他插件的$.fn.alert代码(如果定义),以便在noConflict之后,可以继续使用该旧代码$.fn.alert = function (option) {
return this.each(function () {
// 根据选择器,遍历所有符合规则的元素,然后在元素上绑定插件的实例,以监控用户的事件行为
})
}
$.fn.alert.Constructor = Alert;// 并重设插件构造器,可以通过该属性获取插件的真实类函数
jQuery插件的定义使用了标准的方法,在fn上进行扩展。在附加扩展之前,首先“备份”之前插件(或别的框架提供的同名插件)的旧代码,以方便在后面防冲突的时候使用。在附加扩展之后,重新设置插件的构造器(即Constructor属性)为内部定义的插件类函数自身,这样就可以通过Constructor属性查询到插件的真实类函数,使用new操作符实例化$.fn.alert的时候也不会出错。
注意:即便不声明第三步,HTML声明式的方式也是可以用的。所以说,第三步是专门为某些喜欢用JavaScript代码触发事件的人所准备的。但需要注意的是,如果不声明第三步,那第四步的防冲突的功能也就没法用了。
4、防止冲突处理
例如:$.fn.alert.noConflict
防冲突处理,目的是让Bootstrap插件和其他UI库的同名插件共存。Bootstrap所有的插件都支持防冲突(noConflict)功能。源码如代码清单2-4所示。
// 防冲突处理
$.fn.alert.noConflict = function () {
$.fn.alert = old // 恢复以前的旧代码
return this // 将$.fn.alert.noConflict()设置为Bootstrap的alert插件
}
这样一旦有了一个同名的插件,比如A库里有个同名$.fn.alert插件,则Bootstrap在执行之前就通过old先备份了,然后执行$.fn.alert.noConflict()后就会还原该old对象插件;而使用Bootstrap的alert插件的话,则通过varalert=$.fn.alert.noConflict()的形式,将Bootstrap的alert插件转移到另外一个变量上,从而进行使用。
5、绑定各种触发事件
在一切都就绪之后,绑定默认的触发事件。由于已经为jQuery提供了默认的$.fn.alert扩展插件功能,已经可以通过手工编写JavaScript代码来触发事件了。这里的第五步主要是为声明式的HTML触发事件,即:在HTML文档里已经按照布局规则声明了相关的自定义属性(比如data-dismiss="alert"),然后通过这里的代码初始化默认的单击事件行为(或其他相关插件需要用到的行为)。绑定触发事件的源码如下所示:
// 绑定触发事件
// 为声明式的HTML绑定单击事件
// 在整个document对象上,检测是否有自定义属性data-dismiss="alert"
// 如果有,则设置:单击的时候,关闭指定的警告框元素
$(document).on('click.bs.alert.dataapi',dismiss, Alert.prototype.close)
上述代码在整个document文档上检测自定义属性datadismiss="alert",如果有,则绑定click单击事件(在命名空间bs.alert.data-api上),事件回调函数则是原型方法Alert.prototype.close。这样,一旦单击了相应的元素,就会关闭特定的警告框。
Bootstrap通过这5个通用步骤,定义了所有的插件。每个插件在各个步骤里会有一些细节的不同,但思路都是一样的,那就是:绑定事件,触发行为,并在jQuery上扩展fn,同时解决防冲突的问题。大家在制作自定义插件的时候只要遵从这一思路,即可编写出既易于维护又高质量的插件代码。
2.4.3 通用技术根据上述JavaScript插件的实现步骤,来总结一下JavaScript插件的通用技术,即Bootstrap的开发者在开发这些插件时所制定的规则和遵循的标准,同时也为我们制作自定义插件提供有力的参考。首先,不同插件的JS代码都是单独放在一个JS文件中的,开发人员在使用的时候可以一次性编译到Bootstrap.js,也可以单独使用某一个或者多个JS插件文件。唯一需要注意的是:有些JS插件依赖于其他JS插件,所以不要遗漏了依赖引用。Bootstrap所有的JavaScript插件都可以通过配置使用,即通过特定的HTML设置,而不需要任何JavaScript再次触发。但如果需要启用手动触发事件的行为,可以禁用默认的行为,禁用方法非常简单,只需要将body元素上的命名空间为data-api下的全部事件禁用即可。代码如下所示:
$(document).off('.data-api');
如果想禁用特定插件的默认行为,只需要禁用该插件所在命名空间下的事件即可。代码如下所示:
$(document).off('.alert.data-api');
/* 禁用alert插件的所有默认行为 */
注意off语法是jQuery提供的语法功能,用户在使用on进行绑定事件的时候,可以加命名空间,比如
$().on('click.alert.dataapi')
这样在卸载事件的时候,如果只想卸载该元素的该特定事件,可以使用off('click.alert.data-api')。如果不这样,仅仅使用off('click'),这样该元素上的所有click事件都将被卸载(导致该元素的其他click事件失效)。同理,如果执行off('.data-api')代码,则所有在data-api命名空间下的事件都会被卸载禁用,不管是该选择器内部的哪个元素、哪种事件。
1.可编程性所有的插件不仅可以使用声明式定义(HTML),也可以通过JavaScript代码全部实现。利用jQuery的链式操作,编出的代码非常优美。示例如下所示:
$(".btn.btn-danger").button("toggle").addClass("fat");
所有的插件在使用JavaScript代码调用的时候,都提供多种调用方式:无参数传递(即默认方式)、传递对象字面量进行初始化参数设定、直接传入一个需要执行的方法名称字符串。示例如下所示:
$("#myModal").modal() // 默认值进行初始化
$("#myModal").modal({ keyboard: false }) // 初始化时keyboard选项值是false
$("#myModal").modal('show') // 初始化,然后立即调用show方法
每个插件都有一个Constructor属性,用于表示原始的构造函数,比如$.fn.alert.Constructor。另外也可以通过$('选择符').data('bs.插件名称')的形式(如,$('[datadismiss="alert"]').data('bs.alert'))获取该特定插件的实例。
2.防冲突和jQuery一样,Bootstrap插件可以和其他同类插件共存,为了防止$.fn.下的Bootstrap插件被覆盖,Bootstrap也提供了防冲突功能(No conflict),用于定义别名。示例用法如下:
var bootstrapButton = $.fn.button.noConflict()// 返回$.fn.button对象给bootstrapButton变量
$.fn.bootstrapBtn = bootstrapButton// 将button对象给bootstrapButton变量赋予一个新插件名称
$().bootstrapBtn,这时$().// bootstrapBtn就拥有了先前button的所有功能了
3.自定义事件Bootstrap为很多插件都提供了自定义事件功能,比如,modal弹窗里提供的show和shown事件,show事件在弹窗初始化(即将弹出)的时候触发,而shown事件则是在弹窗初始化完毕后(完全弹出)才触发。在新版插件里,所有的事件都是命名空间化的,即单个事件都要放在某个命名空间下,比如,show.bs.modal。所有的插件都提供了preventDefault功能,用于阻止继续执行后续的代码。例如,可以在modal弹窗的show事件里进行判断,如果不符合条件就拒绝显示弹窗。示例代码如下所示:
$('#myModal').on('show.bs.modal', function (e) {
if (!data) return e.preventDefault() // 拒绝显示弹窗
})
网友评论