Bootstrap 4 中 Alerts 实现

Alert 的使用说明

http://v4-alpha.getbootstrap.com/components/alerts/

JavaScript behavior

Triggers

Enable dismissal of an alert via JavaScript:

$(".alert").alert()

Or with data attributes on a button within the alert, as demonstrated above:

<button type="button" class="close" data-dismiss="alert" aria-label="Close">
  <span aria-hidden="true">&times;</span>
</button>

Note that closing an alert will remove it from the DOM.

Methods

Method Description
$().alert() Makes an alert listen for click events on descendant elements which have the data-dismiss="alert" attribute. (Not necessary when using the data-api’s auto-initialization.)
$().alert(‘close‘) Closes an alert by removing it from the DOM. If the .fade and .in classes are present on the element, the alert will fade out before it is removed.
$(".alert").alert(‘close‘)

Events

Bootstrap’s alert plugin exposes a few events for hooking into alert functionality.

Event Description
close.bs.alert This event fires immediately when the close instance method is called.
closed.bs.alert This event is fired when the alert has been closed (will wait for CSS transitions to complete).
$(‘#myAlert‘).on(‘closed.bs.alert‘, function () {
  // do something…
})

获取 bootstrap 4

bootstrap v4

源代码分析

外层函数分析

从代码的最外层来看,实际上是一个立即执行的函数,jQuery 就是我们熟悉的 jQuery 库。

+function ($) {

} (jQuery);

对于在 function 之前使用 + 的用法,这里有详细的说明:function与感叹号

加上 Alert 之后,我们函数内部会成为嵌套的立即执行函数。

+function ($) {

    var Alert = (function ($) {

    })(jQuery);

} (jQuery);

有点问题,编码风格不一致,这次里面使用了常见的括号方式来处理立即执行函数。

几个辅助函数

创建类的函数 _createClass.

在 JavaScript 中,如何才能定义一个类呢?

类的作用在于同类的对象可以共享处理方法和数据,因此,在类中,必须有一个方式来共享所有同类对象所共享的成员,在 JavaSript 中,基本的方式是通过 function 的原型 prototype 来实现的。定义在 function 的 prototype 对象上的成员,可以被通过这个函数 new 出来的对象所共享。

所以,通常一个类是一个函数,我们把希望共享的成员定义在它的原型对象上。

同时,还可以定义静态的成员,不需要通过对象实例来放问,可以直接通过类型来访问,这些静态成员可以直接定义在这个 function 对象上,没错,function 也是一个对象。

这样的话,在创建一个类的时候,我们需要为这个函数定义实例成员和静态成员,这就是 _createClass 这个函数的职责。

先看简化版本,这个函数不是直接定义出来的,是调用一个匿名函数返回的。这又是一个立即执行函数。

var _createClass = (function () {

    return function () {

    };
})();

在它的内部定义了一个私有的函数,这个函数在外部不可调用。我们再扩展一下。这样看的更加清楚一些。

var _createClass = (function () {

    // 内部的私有函数,外部不可调用.
    function defineProperties(target, props) {
      }
    }

    // 返回的函数,外部可以调用
    return function (Constructor, protoProps, staticProps) {
       defineProperties(Constructor.prototype, protoProps);
       return Constructor;
    };

})();

内部的这个 defineProperties 做什么呢?就是为目标对象定义属性。属性需要实现一些规范: Object.prototype, 下面的代码就是实现规范的要求.

Object.prototype 属性的属性特性:
writable false
enumerable false
configurable false
// define prpperties on object.
function defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if (‘value‘ in descriptor)
      descriptor.writable = true;

    //https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

所以, 创建类型就是传递两个分别描述实例成员和静态成员的数组了.

_createClass 的全部代码如下:

  var _createClass = (function () {

    // define prpperties on object.
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if (‘value‘ in descriptor)
          descriptor.writable = true;

        // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }

    // Constructor: target function
    // protoProps: prototype of function
    // staticProps: static properties
    return function (Constructor, protoProps, staticProps) {
      if (protoProps)
        defineProperties(Constructor.prototype, protoProps);
      if (staticProps)
        defineProperties(Constructor, staticProps);
      return Constructor;
    };
  })();

Alert 定义

里面的 Alert 是一个变量,这个变量是一个内部函数 Alert 返回的. 而这个内部函数就是我们的 Alert 类定义. 可以看到在这个函数定义之后, 就被添加了我们类的成员.

var Alert = (function ($) {
    function Alert(element) {
        _classCallCheck(this, Alert);

        this._element = element;
    }

  _createClass(Alert, [{......}]);

  return Alert;
})();

再看剩下处理内容.

在 document 上注册了一个名为 "click.bs.alert.data-api" 的事件处理程序, 在 jQuery 中吧on 函数的定义如下:

.on( events [, selector ] [, data ], handler )

see also: http://api.jquery.com/on/

第一个参数是事件名称,有可选的选择器,还有事件处理程序.

$(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));

最后, 是适配到 jQuery 的原型中, 以便直接通过 jQuery 对象实例进行处理. 其中的工作NAME 这里就是 alert 了.

/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/

$.fn[NAME] = Alert._jQueryInterface;
$.fn[NAME].Constructor = Alert;
$.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return Alert._jQueryInterface;
};

return Alert;

这里的工作_jQueryInterface 就是一个函数.

function _jQueryInterface(config) {
    return this.each(function () {
        var $element = $(this);
        var data = $element.data(DATA_KEY);

        if (!data) {
            data = new Alert(this);
            $element.data(DATA_KEY, data);
        }

        if (config === ‘close‘) {
            data[config](this);
        }
    });
}

全部的 Alert 代码.

/**
 * --------------------------------------------------------------------------
 * Bootstrap (v4.0.0-alpha.2): alert.js
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

  var Alert = (function ($) {

    /**
     * ------------------------------------------------------------------------
     * Constants
     * ------------------------------------------------------------------------
     */

    var NAME = ‘alert‘;
    var VERSION = ‘4.0.0-alpha‘;
    var DATA_KEY = ‘bs.alert‘;
    var EVENT_KEY = ‘.‘ + DATA_KEY;
    var DATA_API_KEY = ‘.data-api‘;
    var JQUERY_NO_CONFLICT = $.fn[NAME];
    var TRANSITION_DURATION = 150;

    var Selector = {
      DISMISS: ‘[data-dismiss="alert"]‘
    };

    var Event = {
      CLOSE: ‘close‘ + EVENT_KEY,
      CLOSED: ‘closed‘ + EVENT_KEY,
      CLICK_DATA_API: ‘click‘ + EVENT_KEY + DATA_API_KEY
    };

    var ClassName = {
      ALERT: ‘alert‘,
      FADE: ‘fade‘,
      IN: ‘in‘
    };

    /**
     * ------------------------------------------------------------------------
     * Class Definition
     * ------------------------------------------------------------------------
     */

    var Alert = (function () {

      // class define
      function Alert(element) {
        _classCallCheck(this, Alert);

        this._element = element;
      }

      /**
       * ------------------------------------------------------------------------
       * Data Api implementation
       * ------------------------------------------------------------------------
       */

      // getters

      _createClass(Alert, [{
        key: ‘close‘,

        // public

        value: function close(element) {
          element = element || this._element;

          var rootElement = this._getRootElement(element);
          var customEvent = this._triggerCloseEvent(rootElement);

          if (customEvent.isDefaultPrevented()) {
            return;
          }

          this._removeElement(rootElement);
        }
      }, {
          key: ‘dispose‘,
          value: function dispose() {
            $.removeData(this._element, DATA_KEY);
            this._element = null;
          }

          // private

        }, {
          key: ‘_getRootElement‘,
          value: function _getRootElement(element) {
            var selector = Util.getSelectorFromElement(element);
            var parent = false;

            if (selector) {
              parent = $(selector)[0];
            }

            if (!parent) {
              parent = $(element).closest(‘.‘ + ClassName.ALERT)[0];
            }

            return parent;
          }
        }, {
          key: ‘_triggerCloseEvent‘,
          value: function _triggerCloseEvent(element) {
            var closeEvent = $.Event(Event.CLOSE);

            $(element).trigger(closeEvent);
            return closeEvent;
          }
        }, {
          key: ‘_removeElement‘,
          value: function _removeElement(element) {
            $(element).removeClass(ClassName.IN);

            if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
              this._destroyElement(element);
              return;
            }

            $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
          }
        }, {
          key: ‘_destroyElement‘,
          value: function _destroyElement(element) {
            $(element).detach().trigger(Event.CLOSED).remove();
          }

          // static

        }], [{
          key: ‘_jQueryInterface‘,
          value: function _jQueryInterface(config) {
            return this.each(function () {
              var $element = $(this);
              var data = $element.data(DATA_KEY);

              if (!data) {
                data = new Alert(this);
                $element.data(DATA_KEY, data);
              }

              if (config === ‘close‘) {
                data[config](this);
              }
            });
          }
        }, {
            key: ‘_handleDismiss‘,
            value: function _handleDismiss(alertInstance) {
              return function (event) {
                if (event) {
                  event.preventDefault();
                }

                alertInstance.close(this);
              };
            }
          }, {
            key: ‘VERSION‘,
            get: function get() {
              return VERSION;
            }
          }]);

      return Alert;
    })();

    $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));

    /**
     * ------------------------------------------------------------------------
     * jQuery
     * ------------------------------------------------------------------------
     */

    $.fn[NAME] = Alert._jQueryInterface;
    $.fn[NAME].Constructor = Alert;
    $.fn[NAME].noConflict = function () {
      $.fn[NAME] = JQUERY_NO_CONFLICT;
      return Alert._jQueryInterface;
    };

    return Alert;
  })(jQuery);

} (jQuery);

待续......

时间: 2024-10-18 21:28:11

Bootstrap 4 中 Alerts 实现的相关文章

使用Bootstrap.css 中IE下页面加载过慢问题

问题描述: Web中引入bootstrap.css中头部有访问Google服务器的请求 @import url("//fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700"); 国内访问不稳定,页面反应慢 解决:将请求结果保存下来,放到本地,重新声明请求 1.请求http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,4

IE11下,CKEditor在Bootstrap Modal中的下拉问题

原问题解决方案链接:http://ckeditor.com/forums/CKEditor/Editor-Dropdowns-dont-work-in-IE11 最近在项目中需要在Bootstrap Modal弹出框中载入CKEditor. 初始化CKEditor以后,在IE11下,格式/字体/颜色的下拉会闪现一下后就消失,但在chrome和firefox下没问题. Google了以后终于找到解决方法. 以下代码添加了$(e.target.parentNode).hasClass('cke_co

在Bootstrap开发框架中使用dataTable直接录入表格行数据(2)--- 控件数据源绑定

在前面随笔<在Bootstrap开发框架中使用dataTable直接录入表格行数据>中介绍了在Web页面中使用Jquery DataTable插件进行对数据直接录入操作,这种处理能够给用户提供较好的数据录入体验,本篇继续上篇的内容,继续介绍这个直接录入的处理操作,主要涉及到控件的初始化和数据源的绑定等操作内容,随着对这个处理的深入了解,我发现可以控制的内容也更加丰富,能够更好的实现各种所需的效果. 1.直接录入数据的界面分析 在之前介绍的数据直接录入处理的时候,界面效果如下所示. 上面的界面处

解决 select2在bootstrap modal中不能正常使用问题

select2在bootstrap modal中不能正常使用问题 设置CSS .select2-drop { z-index: 10050 !important; } .select2-search-choice-close { margin-top: 0 !important; right: 2px !important; min-height: 10px; } .select2-search-choice-close:before { color: black !important; } /

Bootstrap中alerts的用法

警告alerts的使用:用于提示用户相关信息.  基本的显示方式有四种分别对应的是:(信息)alert-info .(成功)alert-success.(危险)alert-danger.(警告)alert-warning.示例代码: <div class="alert alert-info">文字的信息提示</div> <div class="alert alert-success">成功的信息提示</div> <

关于【bootstrap】中,【tooltip】的不算bug的bug的个人看法

先说下遇到这个问题的背景吧. 就是在页面中有个div,这个div右上角(或者其他位置)有个 × 的图标(这个图标添加tooltip工具提示),光标移到这个图标时,触发tooltip,提示“点击移除”这样类似的字样,然后点击后,把这个div作remove()这样的删除操作. 然后,问题来了,因为这个div被remove()了,导致生成的tooltip对应的 × 图标也被remove(),因为找不到,所以对应的mouseout(可能是mouseleave事件,参考了一下bootstrap的源码,没找

bootstrap框架中data-toggle=&quot;tab&quot;属性会取消a标签默认行为

这几天做公司项目用了bootstrap框架,在用导航组件的过程中,我发现在a标签里面添加data-toggle="tab"属性之后,这个a标签会失去默认行为,点击a标签的时候不会跳转,即使有href属性,但是它不管用.So,如果想要实现它导航栏的效果,又要能够让链接有效,只能去掉data-toggle="tab"属性.但是动态切换导航按钮的active属性就实现不了,但是实现了跳转,active属性还有什么用呢?就算有也看不到(小记)

修复bootstrap daterangepicker中的3个问题

最近项目中使用了一个基于Bootstrap的daterangepicker控件. 1.点击页面其他空白的地方,会把之前在日历上选中的日期选择上. 具体描述: 1.点击打开日期选择框 2.选择一个日期范围,用户没有点击"Apply"按钮,然后点击页面其他空白区域,控件会把选择的日期赋值到文本框中去. 这个需求估计在国外属于正常的情况.但是国内的用户习惯是:点击其他空白地方,应该是和点击"取消"按钮相同的作用.所以看了一下源代码.在outsideClick方法里面,作者

Bootstrap框架中的字形图标的理解

最近项目中准备使用 Bootstrap 框架,看中了Ace Admin 这套皮肤,看其代码的时候,发现使用了字形图标.下面内容来源于网络,根据自己对新知识的学习曲线重新整合了一下: 一,字形图标的定义和产生原因: 字形图标(Glyphicons)是在 Web 项目中使用的图标字形.虽然,Glyphicons Halflings 需要商业许可,但是您可以通过基于项目的 Bootstrap 来免费使用这些图标. 为了表示对图标作者的感谢,希望您在使用时加上 GLYPHICONS 网站的链接.(原文)