JavaScript插件架构

时间:2022-12-08 07:18:19

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个实现步骤。

JavaScript插件架构

  下面以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。这样,一旦单击了相应的元素,就会关闭特定的警告框。