Bootstrapソースコード解析

12389 ワード

1.Bootstrapの役割ドメイン
2.Bootstrapのクラス定義
3、Bootstrapのプラグイン定義
4、Bootstrapのイベントエージェント
5.Bootstrapのオブジェクトデータキャッシュ
6、Bootstrapの衝突防止
7、作用域外でのButton類の使用方法
8、Bootstrapのユニットテスト
 
 
Bootstrapの役割ドメイン
Bootstrapの各プラグインは、次の役割ドメインコードで定義されています.
+function ($) {

    ...

}(window.jQuery)

IIFE」と「厳格モード」のコンパイル環境を参照してください.
 
プラグインの役割ドメイン以外では,グローバルレンジでコードの最初の行が実行され,jQueryが定義されているか否かが検出される.Gruntのconcatタスクで、すべてのプラグインをマージすると、検出コードがターゲットファイルのbanner説明の後に追加されます.Grunt.jsの関連コード:
jqueryCheck: 'if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") }

', 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プラグイン開発クイックスタート」を参照してください.この2つは異なるオブジェクトを指していることに注意してください.
  $.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