Bootstrap JS外掛Alert原始碼分析

cjf_580232abde0df發表於2017-11-27

1、先附上alert的原始碼
將Alert放在自執行函式中,避免變數汙染

/* ====================================================================
 * Bootstrap: alert.js v3.3.7
 * http://getbootstrap.com/javascript/#alerts
 * ====================================================================
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */
+function ($) {
  `use strict`; //使用嚴格模式 執行js程式碼

  var dismiss = `[data-dismiss="alert"]` //alert警告框事件選擇器
  var Alert   = function (el) {  //alert警告框建構函式
    $(el).on(`click`, dismiss, this.close)//選擇器繫結點選關閉alert警告框的事件
  }

  Alert.VERSION = `3.3.7`//版本
  Alert.TRANSITION_DURATION = 150//過渡時間  為了讓警告框在關閉時表現出動畫效果

  Alert.prototype.close = function (e) {//在alert原型上新增close方法
    var $this    = $(this)//當前物件包裝成jquery物件
    var selector = $this.attr(`data-target`) //獲取jquery物件的date-target屬性值

    if (!selector) {//如果沒有獲取到
      selector = $this.attr(`href`)//獲取href屬性值
      selector = selector && selector.replace(/.*(?=#[^s]*$)/, ``) // strip for ie7
    }

    var $parent = $(selector === `#` ? [] : selector)//如果selector是#則返回空陣列,返回自身

    if (e) e.preventDefault()//取消事件的預設動作 a標籤的連結不會開啟

    if (!$parent.length) {
      $parent = $this.closest(`.alert`)//找到祖先中類名為alert的元素
    }

    $parent.trigger(e = $.Event(`close.bs.alert`))//觸發自定義的close.bs.alert事件 
    //並將e重新複製

    if (e.isDefaultPrevented()) return //e被重新賦值為jquery事件物件 e.isDefaultPrevented()值為false  不會走return語句

    $parent.removeClass(`in`)//刪除具有動畫效果的 類 

    function removeElement() {
      // detach from parent, fire event then clean up data
      //detach刪除匹配元素,但是不從jquery物件上刪除
      //remove刪除元素,元素對應的事件,資料,全部移除
      //元素動畫效果結束後觸發closed.bs.alert事件,並移除
      $parent.detach().trigger(`closed.bs.alert`).remove()
    }
    //探測瀏覽器是否支援transition,以及祖先元素是否包含fade類,如果都支援,
    //在關閉alert警告框時,會有動畫效果,如果不支援則直接刪除

    $.support.transition && $parent.hasClass(`fade`) ?
      $parent
        .one(`bsTransitionEnd`, removeElement)
        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
      removeElement()
  }
  //對外暴露的函式
  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      //獲取元素上設定的資料
      var data  = $this.data(`bs.alert`)
    //如果沒有對應的設定資料,則重新設定
      if (!data) $this.data(`bs.alert`, (data = new Alert(this)))
      //判斷傳入的option是否為String型別,是則呼叫Alert例項的對應方法
      if (typeof option == `string`) data[option].call($this)
    })
  } 
 //儲存一份alert引用
  var old = $.fn.alert
 //jquery例項上的alert方法,當呼叫該方法是遍歷所有的選中的元素,設定對應的data,並呼叫其原型的close方法,
  $.fn.alert             = Plugin
  $.fn.alert.Constructor = Alert

  //當alert方法衝突時,呼叫次方法避免衝突
  $.fn.alert.noConflict = function () {
    $.fn.alert = old
    return this
  }
  //在document上繫結事件 ,通過jquery的off方法,可以解除該事件
  $(document).on(`click.bs.alert.data-api`, dismiss, Alert.prototype.close)
}(jQuery);

2、使用

<div class="alert alert-warning">
    <button type="button" class="close" data-dismiss="alert">
        &times;
    </button>
    警告!請不要提交。
</div>
<div class="alert alert-danger">
    <a href="#" class="close" data-dismiss="alert">
        &times;
    </a>
    錯誤!請進行一些更改。
</div>

3、呼叫
當我們呼叫

$(".alert").alert(`close`)

的時候,就會呼叫原始碼中Plugin函式,遍歷所有的警告框,並關閉。

4、解除警告框點選關閉事件,傳入對應的事件名稱空間(namespace)即可

$(document).off(`.bs.alert.data-api`) 

相關文章