Bootstrap 源码解析(转)
1、Bootstrap的作用域
2、Bootstrap的类定义
3、Bootstrap的插件定义
4、Bootstrap的事件代理
5、Bootstrap的对象数据缓存
6、Bootstrap的防冲突
7、作用域外如何使用Button类
8、Bootstrap的单元测试
Bootstrap的作用域
Bootstrap每个插件都定义在下面这段作用域代码中:
+function ($) {
...
}(window.jQuery)
在插件的作用域之外,全局范围执行代码的第一行,检测了jQuery是否定义。在Grunt的concat任务中,合并所有插件时,检测代码添加在目标文件的banner说明后面。Grunt.js的相关代码:
jqueryCheck: 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") }\n\n',
concat: {
options: {
banner: '<%= banner %><%= jqueryCheck %>',
stripBanners: false
},
bootstrap: {
src: [
'js/transition.js',
'js/alert.js',
'js/button.js',
'js/carousel.js',
'js/collapse.js',
'js/dropdown.js',
'js/modal.js',
'js/tooltip.js',
'js/popover.js',
'js/scrollspy.js',
'js/tab.js',
'js/affix.js'
],
dest: 'dist/js/<%= pkg.name %>.js'
}
}
Bootstrap的类定义
var Button = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Button.DEFAULTS, options)
}
Button.DEFAULTS = {
loadingText: 'loading...'
}
Button.prototype.setState = function (state) {
...
}
Button.prototype.toggle = function () {
...
}
Bootstrap采用这种类定义方式的好处,以及Javascript其他几种类定义的方式,请参照《Javascript面向对象编程(一):封装》
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。在Button函数体内部定义的属性和方法可以看做是类的私有属性和方法, 为Button.prototype对象定义的属性和方法都可以看做是类的公共属性和方法。这个类封装了插件对象初始化所需的方法和属性。
Bootstrap的插件定义
请参看《jQuery插件开发快速入门》,注意两个this指向的是不同对象
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this)
...
})
}
Bootstrap的事件代理
Bootstrap Button插件定义最后一部分,事件绑定是这么写的
$(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
...
})
这段JavaScript代码将click委托事件监听器绑定在document元素上,并给click事件赋予命名空间click.bs.button.data-api,选择器匹配的是属性data-toggle的值为"button"开头的标签。
关于jQuery将事件绑定在document文档对象上的好处,就是js事件代理的优点,性能上做了一个测试比较。
关于jQuery命名空间的好处,请参看《jQuery .on() and .off() 命名空间》
Bootstrap的防止冲突
jQuery是全局对象,所以jQuery的插件定义$.fn.button并不受作用域限制。如果在别的插件中同样定义了button插件,后加载的button插件将会覆盖先加载的button插件,jsbin示例:
// Old button
+function($){
$.fn.button = function() {
alert('Old button')
}
}(window.jQuery) // Bootstrap button
+function($){
$.fn.button = function() {
alert('Bootstrap button')
}
}(window.jQuery) $('a').button() // alert('Bootstrap button')
Bootstrap做了插件冲突处理,jsbin示例:
// Old button
+function($) {
$.fn.button = function() {
alert('Old button')
}
}(window.jQuery) // Bootstrap button
+function($){
// 将原先的button插件对象赋值给一个临时变量old
var old = $.fn.button $.fn.button = function() {
alert('Bootstrap button')
} // 执行该函数,恢复原先的button定义,并返回Bootstrap定义的button插件
$.fn.button.noConflict = function () {
$.fn.button = old
return this
} }(window.jQuery) // <span style="font-family: Helvetica, Tahoma, Arial, sans-serif; white-space: normal; background-color: #ffffff;">作用域</span>外我们可以灵活使用两个button插件
$.fn.button = $.fn.button.noConflict()
$('a').button() // alert('Bootstrap button') $.fn.button.noConflict()
$('a').button() // alert('Old button')
Bootstrap作用域外如何使用Button类
$.fn.button.Constructor = Button
在Bootstrap的button插件中还有上面者句代码,去掉它不影响插件的正确执行。
它很像javascript中类构造器:
var Cat = function(name) {
this.name = name
}
var cat1 = new Cat('Hello Kitty')
var cat2 = new Cat('Doramon')
cat1.constructor == Cat.prototype.constructor
但是Javascript是区分大小写的,也就是 这里大写开头的的Constructor 和 Javascript小写开头的constructor 没有任何关系。
查找jQuery源码中也没有对于大写开头的Constructor的定义。所以这里的Constructor只是一个普通属性,我们也可以写成其他名字 $.fn.button.Something = Button,Bootstrap为了指明这个属性的意义而命名为构造器“Constructor”更合理。
这样一来,这段代码就很好理解了:$.fn.button.Constructor = Button 通过将作用域内的Button类赋值给jQuery的button对象的Constructor属性,在IIFE作用域外也可以使用Button类。调用方式:
+function($){
// 类定义
var Button = function() {}
// 插件定义
$.fn.button = function() {
alert('Bootstrap button')
}
// 类赋值到jQuery button对象的Constructor属性
$.fn.button.Constructor = Button
}(window.jQuery)
var Button = $.fn.button.Constructor
Bootstrap的对象数据缓存
// 获取存储的Button对象,如果是第一次执行变量data的值为undefined
var data = $this.data('bs.button')
var options = typeof option == 'object' && option // 创建Button对象: new Button(this, options),
// 并赋值给变量data: data = new Button(this, options)
// 存储在元素的jQuery对象上的‘bs.button’数据字段 $this.data('bs.button', data)
if (!data) $this.data('bs.button', (data = new Button(this, options))) // data是一个Button对象,可以调用Button的原生方法
if (option == 'toggle') data.toggle()
else if (option) data.setState(option)
利用jQuery的 .data(key, value)存储Button对象
Bootstrap的单元测试
QUnit + PhantomJS
优秀的程序猿有一个共同的秘诀:阅读优秀的代码。
http://suqing.iteye.com/blog/1984131
Bootstrap 源码解析(转)的更多相关文章
- 转载:Bootstrap 源码解析
Bootstrap 源码解析 前言 Bootstrap 是个CSS库,简单,高效.很多都可以忘记了再去网站查.但是有一些核心的东西需要弄懂.个人认为弄懂了这些应该就算是会了.源码看一波. 栅格系统 所 ...
- [Bootstrap 源码解析]——bootstrap源码之初始化
bootstrap源码之初始化 我们先来分析normalize.less编译后的源码,我们知道normalize.css是一个专门将不同浏览器的默认css特性设置为统一效果的css库,它和reset. ...
- Bootstrap 源码解析
前言 Bootstrap 是个CSS库,简单,高效.很多都可以忘记了再去网站查.但是有一些核心的东西需要弄懂.个人认为弄懂了这些应该就算是会了.源码看一波. 栅格系统 所谓的栅格系统其实就是一种布局方 ...
- Appium Android Bootstrap源码分析之命令解析执行
通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...
- 实战录 | Kafka-0.10 Consumer源码解析
<实战录>导语 前方高能!请注意本期攻城狮幽默细胞爆表,坐地铁的拉好把手,喝水的就建议暂时先别喝了:)本期分享人为云端卫士大数据工程师韩宝君,将带来Kafka-0.10 Consumer源 ...
- Appium Android Bootstrap源码分析之启动运行
通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...
- Appium Android Bootstrap源码分析之控件AndroidElement
通过上一篇文章<Appium Android Bootstrap源码分析之简介>我们对bootstrap的定义以及其在appium和uiautomator处于一个什么样的位置有了一个初步的 ...
- Netty5客户端源码解析
Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...
- Netty5服务端源码解析
Netty5源码解析 今天让我来总结下netty5的服务端代码. 服务端(ServerBootstrap) 示例代码如下: import io.netty.bootstrap.ServerBootst ...
随机推荐
- 安装 php 转
一 安装 php 命令: sudo apt-get install libapache2-mod-php5 php5 出现了如下错误: 按照方案一 解决了此问题. 一下 from http://w ...
- Beaglebone Back学习五(PWM测试)
PWM测试 参考链接 1 Enable PWM on BeagleBone with Device Tree overlays 2Using PWM on the Beaglebone Black 3 ...
- Android开发中Eclipse里的智能提示设置
今天开始学习一下Android开发,直接在Android Developers下载的一个开发工具包,然后再下了一个JDK,配置完环境变量等一系列的工作后环境就搭建好了,在新建好第一个Android项目 ...
- eclipse 僵死/假死 问题排查及解决
症状: 使用Eclipse win 64位版本,indigo及kepler都重现了,使用tomcat 6.0.39,jdk1.6.u45及1.7u45均尝试了,也重现. 重现步骤很简单,使用debug ...
- Asp.net MVC入门视频教程
编程开发 > Asp.net视频教程 > Asp.net MVC入门视频教程 > 1.传统web处理方式和mvc处理方式 上传日期:2014-08-16 10:02:45 相关摘要 ...
- SecureCRT上传bash: rz: command not found(转载)
转载自:http://blog.csdn.net/zhangdaiscott/article/details/18141017 -bash: rz: command not found rz命令没找到 ...
- html 页面 ajax 方法显示遮罩
showLoading.css 样式: ;;list-style-type:none;} a,img{;} .overlay{;;;;;width:100%;height:100%;_padding: ...
- js 判断对象相等
文笔不是很好,一直在博客园属于那种只看不说的那种,有次心血来潮,想把自己的一些心得记录下来,我认认真真写了大半个小时,谁知一点保存,会话超时然后我的东西不知道去哪里,当时想死的心都有,写博客也就没那个 ...
- 1194: [HNOI2006]潘多拉的盒子 - BZOJ
Description Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语机S-1的顺序描述.每一块的 ...
- mysql 跨库JOIN
现有两台MYSQL数据库 一台是192.168.1.1 端口3306 上有数据库DB1 有表TABLE1一台是192.168.1.2 端口3307 上有数据库DB2 有表TABLE2192.168.1 ...