JavaScript插件架构
1.HTML布局规则
默认情况下,所有的插件都可以通过设置特定的HTML代码和相应的属性来实现。也就是说,在网页加载的时候,JavaScript代码会自动检测这些标记,并自动绑定相应的事件,而无需添加额外的JavaScript代码。示例如下:
<div class="alert"> <button type="button" class="close" data-dismiss="alert">×</button> <strong>警告!</strong> 你输入的项目不合法! </div>
上述代码是警告框组件的HTML布局,只要在button元素上添加一个data-dismiss="alert"属性,那么在单击该button的时候就会关闭该警告框。类似如easyui框架的data-options属性。
<select id="selectDealerAdd" name="selectDealerAdd" class="easyui-combobox" style="width:150px; height:32px;" data-options="onSelect: function (record) {$('#hiddenDealerAdd').val(record.value);}"> <% foreach (var i in models) {%> <option value="<%=i.EmpId.Trim()%>"><%=i.Name.Trim()%></option> <% } %> </select> <asp:HiddenField ID="hiddenDealerAdd" runat="server" Value=""/>
同理,如下代码是下拉菜单的HTML布局,只要保证所单击的button按钮添加了data-toggle="dropdown"属性,在单击按钮的时候,默认隐藏的下拉菜单就会显示出来。
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>Bootstrap 101 Template</title> <!-- Bootstrap --> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <h1>你好,世界!</h1> <ul class="nav nav-tabs" id="myTab"> <li class="active"><a data-toggle="tab" href="#home">首页</a></li> <li class=""><a data-toggle="tab" href="#profile">个人资料</a></li> <li class="dropdown"> <!-- 单击"我的书籍"时,弹出下拉菜单 --> <a data-toggle="dropdown" href="#" class="dropdown-toggle">我的书籍 <b class="caret"></b> </a> <ul class="dropdown-menu"> <li><a data-toggle="tab" href="#dropdown1">JavaScript编程精解</a></li> <li><a data-toggle="tab" href="#dropdown2">JavaScript设计模式</a></li> <li><a data-toggle="tab" href="#dropdown3">JavaScript启示录</a></li> <li><a data-toggle="tab" href="#dropdown4">深入理解Bootstrap</a></li> </ul> </li> </ul> <div class="tab-content" id="myTabContent"> <div id="home" class="tab-pane fade active in"> <p>单击"首页"时显示该区域</p> </div> <div id="profile" class="tab-pane fade"> <p>单击"个人资料"时显示该区域</p> </div> <div id="dropdown1" class="tab-pane fade"> <p>单击"JavaScript编程精解"时显示该区域</p> </div> <div id="dropdown2" class="tab-pane fade"> <p>单击"JavaScript设计模式"时显示该区域</p> </div> <div id="dropdown3" class="tab-pane fade"> <p>单击"JavaScript启示录"时显示该区域</p> </div> <div id="dropdown4" class="tab-pane fade"> <p>单击"深入理解Bootstrap3"时显示该区域</p> </div> </div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="js/bootstrap.min.js"></script> </body> </html>
2.JavaScript实现步骤
Bootstrap里提供的所有JavaScript插件都统一遵循了下面这样的5个实现步骤。

下面以alert插件为例(alert.js)讲述一下如何实现标准的插件。
步骤1定义一个立即调用的函数声明。在参数里传入jQuery对象,通过参数$引入变量。这样的做法,有以下两个好处:
- 函数内部的$符号变量代表了局部变量,而不是全局变量里代表jQuery的$符变量,以达到防止变量污染的目的。
- 内部的代码全部都是私有代码,外部代码无法访问,只有通过第三步,在$.fn设置了插件(比如$.fn.alert=)的形式,通过$符变量才能将整个插件通过唯一的接口$.fn.alert暴露出去,从而保护了其内部代码。
+function ($) { "use strict";
// 1.使用严格模式ES5支持 // 2.alert插件类及原型方法的定义 // 3.在jQuery上定义alert插件,并重设插件构造器重设插件构造器,可以通过该属性获取插件的真实类函数 // 4. 防冲突处理 // 5. 绑定触发事件 }(window.jQuery);
步骤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) { // 关闭警告框的主要代码设置 }
通过上述代码可以看出,主要是先定义了插件的类函数Alert,然后再定义需要用到的一些原型函数,比如close函数方法。Alert函数接收el参数,el参数表示DOM元素,一个BOM如果绑定了data-dismiss="alert"自定义属性,则在单击的时候就会触发close函数方法,从而达到关闭的目的。
步骤3在jQuery上定义插件,以便通过jQuery.[插件名称]()的方式,也能够使用该插件。
// 在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操作符实例化$.alert的时候也不会出错。
步骤4防冲突处理,目的是让Bootstrap插件和其他UI库的同名插件共存。
// 防冲突处理 $.fn.alert.noConflict = function () { $.fn.alert = old // 恢复以前的旧代码 return this // 将$.fn.alert.noConflict()设置为Bootstrap的alert插件 }
这样一旦有了一个同名的插件,比如A库里又个同名$.fn.alert插件,则Bootstrap在执行之前就通过old先备份了,然后通过var alert=$.fn.alert.noConflict()的形式,将Bootstrap的alert插件专业到另外一个变量上,从而进行使用。
步骤5在一切都就绪之后,绑定默认的触发事件。这里的第五步主要是申明式的HTML触发事件,即在HTML文档里已经按照布局规则声明了相关的自定义属性(比如data-dismiss="alert"),然后公共这里的代码初始化默认的单击事件行为。绑定触发事件的源代码如下:
// 绑定触发事件 // 为声明式的HTML绑定单击事件 // 在整个document对象上,检测是否有自定义属性data-dismiss="alert" // 如果有,则设置:单击的时候,关闭指定的警告框元素 $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
上述代码在整个document文档上减仓自定义属性data-dismiss="alert",如果有,则绑定click单击事件(在命名空间bs.alert.data-api上),事件回到函数这是原型方法Alert.prototype.close。这样,一旦单击了相应的元素,就会关闭特定的警告框。
浙公网安备 33010602011771号