1、Bootstrap的作用域

2、Bootstrap的类定义

3、Bootstrap的插件定义

4、Bootstrap的事件代理

5、Bootstrap的对象数据缓存

6、Bootstrap的防冲突

7、作用域外如何使用Button类

8、Bootstrap的单元测试

Bootstrap的作用域

Bootstrap每个插件都定义在下面这段作用域代码中:

  1. +function ($) {
  2. ...
  3. }(window.jQuery)

请看《IIFE》和《严格模式》编译环境。

在插件的作用域之外,全局范围执行代码的第一行,检测了jQuery是否定义。在Grunt的concat任务中,合并所有插件时,检测代码添加在目标文件的banner说明后面。Grunt.js的相关代码:

  1. jqueryCheck: 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") }\n\n',
  2.  
  3. concat: {
  4. options: {
  5. banner: '<%= banner %><%= jqueryCheck %>',
  6. stripBanners: false
  7. },
  8. bootstrap: {
  9. src: [
  10. 'js/transition.js',
  11. 'js/alert.js',
  12. 'js/button.js',
  13. 'js/carousel.js',
  14. 'js/collapse.js',
  15. 'js/dropdown.js',
  16. 'js/modal.js',
  17. 'js/tooltip.js',
  18. 'js/popover.js',
  19. 'js/scrollspy.js',
  20. 'js/tab.js',
  21. 'js/affix.js'
  22. ],
  23. dest: 'dist/js/<%= pkg.name %>.js'
  24. }
  25. }

Bootstrap的类定义

  1. var Button = function (element, options) {
  2. this.$element = $(element)
  3. this.options = $.extend({}, Button.DEFAULTS, options)
  4. }
  5.  
  6. Button.DEFAULTS = {
  7. loadingText: 'loading...'
  8. }
  9.  
  10. Button.prototype.setState = function (state) {
  11. ...
  12. }
  13.  
  14. Button.prototype.toggle = function () {
  15. ...
  16. }

Bootstrap采用这种类定义方式的好处,以及Javascript其他几种类定义的方式,请参照《Javascript面向对象编程(一):封装

Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。在Button函数体内部定义的属性和方法可以看做是类的私有属性和方法, 为Button.prototype对象定义的属性和方法都可以看做是类的公共属性和方法。这个类封装了插件对象初始化所需的方法和属性。

Bootstrap的插件定义

请参看《jQuery插件开发快速入门》,注意两个this指向的是不同对象

  1. $.fn.button = function (option) {
  2. return this.each(function () {
  3. var $this = $(this)
  4. ...
  5. })
  6. }

Bootstrap的事件代理

Bootstrap Button插件定义最后一部分,事件绑定是这么写的

  1. $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
  2. ...
  3. })

这段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示例

  1. // Old button
  2. +function($){
  3. $.fn.button = function() {
  4. alert('Old button')
  5. }
  6. }(window.jQuery)
  7.  
  8. // Bootstrap button
  9. +function($){
  10. $.fn.button = function() {
  11. alert('Bootstrap button')
  12. }
  13. }(window.jQuery)
  14.  
  15. $('a').button() // alert('Bootstrap button')

Bootstrap做了插件冲突处理,jsbin示例

  1. // Old button
  2. +function($) {
  3. $.fn.button = function() {
  4. alert('Old button')
  5. }
  6. }(window.jQuery)
  7.  
  8. // Bootstrap button
  9. +function($){
  10. // 将原先的button插件对象赋值给一个临时变量old
  11. var old = $.fn.button
  12.  
  13. $.fn.button = function() {
  14. alert('Bootstrap button')
  15. }
  16.  
  17. // 执行该函数,恢复原先的button定义,并返回Bootstrap定义的button插件
  18. $.fn.button.noConflict = function () {
  19. $.fn.button = old
  20. return this
  21. }
  22.  
  23. }(window.jQuery)
  24.  
  25. // <span style="font-family: Helvetica, Tahoma, Arial, sans-serif; white-space: normal; background-color: #ffffff;">作用域</span>外我们可以灵活使用两个button插件
  26. $.fn.button = $.fn.button.noConflict()
  27. $('a').button() // alert('Bootstrap button')
  28.  
  29. $.fn.button.noConflict()
  30. $('a').button() // alert('Old button')

Bootstrap作用域外如何使用Button类

  1. $.fn.button.Constructor = Button

在Bootstrap的button插件中还有上面者句代码,去掉它不影响插件的正确执行。

它很像javascript中类构造器:

  1. var Cat = function(name) {
  2. this.name = name
  3. }
  4. var cat1 = new Cat('Hello Kitty')
  5. var cat2 = new Cat('Doramon')
  6.  
  7. 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类。调用方式:

  1. +function($){
  2. // 类定义
  3. var Button = function() {}
  4. // 插件定义
  5. $.fn.button = function() {
  6. alert('Bootstrap button')
  7. }
  8. // 类赋值到jQuery button对象的Constructor属性
  9. $.fn.button.Constructor = Button
  10.  
  11. }(window.jQuery)
  12.  
  13. var Button = $.fn.button.Constructor

Bootstrap的对象数据缓存

  1. // 获取存储的Button对象,如果是第一次执行变量data的值为undefined
  2. var data = $this.data('bs.button')
  3. var options = typeof option == 'object' && option
  4.  
  5. // 创建Button对象: new Button(this, options),
  6. // 并赋值给变量data: data = new Button(this, options)
  7. // 存储在元素的jQuery对象上的‘bs.button’数据字段 $this.data('bs.button', data)
  8. if (!data) $this.data('bs.button', (data = new Button(this, options)))
  9.  
  10. // data是一个Button对象,可以调用Button的原生方法
  11. if (option == 'toggle') data.toggle()
  12. else if (option) data.setState(option)

利用jQuery的 .data(key, value)存储Button对象

Bootstrap的单元测试

QUnit + PhantomJS

优秀的程序猿有一个共同的秘诀:阅读优秀的代码。

http://suqing.iteye.com/blog/1984131

Bootstrap 源码解析(转)的更多相关文章

  1. 转载:Bootstrap 源码解析

    Bootstrap 源码解析 前言 Bootstrap 是个CSS库,简单,高效.很多都可以忘记了再去网站查.但是有一些核心的东西需要弄懂.个人认为弄懂了这些应该就算是会了.源码看一波. 栅格系统 所 ...

  2. [Bootstrap 源码解析]——bootstrap源码之初始化

    bootstrap源码之初始化 我们先来分析normalize.less编译后的源码,我们知道normalize.css是一个专门将不同浏览器的默认css特性设置为统一效果的css库,它和reset. ...

  3. Bootstrap 源码解析

    前言 Bootstrap 是个CSS库,简单,高效.很多都可以忘记了再去网站查.但是有一些核心的东西需要弄懂.个人认为弄懂了这些应该就算是会了.源码看一波. 栅格系统 所谓的栅格系统其实就是一种布局方 ...

  4. Appium Android Bootstrap源码分析之命令解析执行

    通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...

  5. 实战录 | Kafka-0.10 Consumer源码解析

    <实战录>导语 前方高能!请注意本期攻城狮幽默细胞爆表,坐地铁的拉好把手,喝水的就建议暂时先别喝了:)本期分享人为云端卫士大数据工程师韩宝君,将带来Kafka-0.10 Consumer源 ...

  6. Appium Android Bootstrap源码分析之启动运行

    通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...

  7. Appium Android Bootstrap源码分析之控件AndroidElement

    通过上一篇文章<Appium Android Bootstrap源码分析之简介>我们对bootstrap的定义以及其在appium和uiautomator处于一个什么样的位置有了一个初步的 ...

  8. Netty5客户端源码解析

    Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...

  9. Netty5服务端源码解析

    Netty5源码解析 今天让我来总结下netty5的服务端代码. 服务端(ServerBootstrap) 示例代码如下: import io.netty.bootstrap.ServerBootst ...

随机推荐

  1. .NET基础之深度复制和浅度复制

    之前一直没有搞清楚深度复制和浅度复制的区别到底在哪里,今天彻底把这个东西弄懂了,写出来与到家共勉. 如果大家不懂值类型和引用类型的区别,请先看http://www.cnblogs.com/Autumo ...

  2. WPF学习笔记4——Layout之2

    下面简单介绍常见的面板. 一.Grid 1.Grid关于调整行列距离有三种方法:绝对大小,自动大小,比例大小.如下: <ColumnDefinition Width="100" ...

  3. Java实现MySQL在线管理

    问题: 1.如何实现在线创建MySQL数据库.表: 2.如何实现在线执行sql语句? 思路: 1.可以通过java.sql.Statement类的executeUpdate(String sql)方法 ...

  4. Perl中的特殊内置变量详解

    #!/usr/bin/perl -w @array = qw(a b c d); foreach (@array) { print $_," "; } 例子的作用就是定义一个数组并 ...

  5. php使用注意点

    php使用时间之前要将php.ini中时区设置好,否则会报警告.截图如下:“;date.timezone =”设置为“date.timezone =Asia/Shanghai”即可. apache如果 ...

  6. .NET安装和配置Oracle数据访问组件(ODAC)

    Many ASP.NET applications access Oracle database for the data source. Oracle supports the .NET with ...

  7. XSS前端防火墙

    前一段时间,在EtherDream大神的博客里看到关于XSS防火墙的一系列文章,觉得很有意思.刚好科创要做一个防火墙,就把XSS前端防火墙作为一个创新点,着手去实现了. 在实现过程中,由于各种原因,比 ...

  8. ssh scp访问ipv6地址

    从这里学来的.http://blog.mattandanne.org/2012/01/sftpscp-and-ipv6-link-local-addresses.html当采用ipv6的地址去连接另外 ...

  9. PAT-乙级-1024. 科学计数法 (20)

    1024. 科学计数法 (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 HOU, Qiming 科学计数法是科学家用来表示很 ...

  10. 团体程序设计天梯赛-练习集L2-003. 月饼

    L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...