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);
}
});
}

注册事件处理函数

// Event.CLICK_DATA_API: click.bs.alert.data-api
// Selector.DISMISS: [data-dismiss="alert"]
// register a event handler
$(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));

注意,这里的事件名称并不是通常的 click, 而是 click.bs.alert.data-api,这里涉及到 jQuery 的事件命名空间问题,可以到这里参考 jQuery 的文档:http://api.jquery.com/on/#event-names

作用就是我们可以在取消某些事件处理注册的时候,不会影响其它已经注册的事件处理程序。

目标选择器则为:[data-dismiss="alert"] ,这正是 bootstrap 所要求的按钮必须拥有的属性。

全部的 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);

使用的样式

.alert {
padding: 15px;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: .25rem;
} .alert > p,
.alert > ul {
margin-bottom:;
} .alert > p + p {
margin-top: 5px;
} .alert-heading {
color: inherit;
} .alert-link {
font-weight: bold;
} .alert-dismissible {
padding-right: 35px;
} .alert-dismissible .close {
position: relative;
top: -2px;
right: -21px;
color: inherit;
} .alert-success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d0e9c6;
} .alert-success hr {
border-top-color: #c1e2b3;
} .alert-success .alert-link {
color: #2b542c;
} .alert-info {
color: #31708f;
background-color: #d9edf7;
border-color: #bcdff1;
} .alert-info hr {
border-top-color: #a6d5ec;
} .alert-info .alert-link {
color: #245269;
} .alert-warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faf2cc;
} .alert-warning hr {
border-top-color: #f7ecb5;
} .alert-warning .alert-link {
color: #66512c;
} .alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebcccc;
} .alert-danger hr {
border-top-color: #e4b9b9;
} .alert-danger .alert-link {
color: #843534;
}

待续......

Bootstrap 4 中 Alerts 实现的更多相关文章

  1. bootstrap Table 中给某一特定值设置table选中

    bootstrap Table 中给某一特定值设置table选中 需求: 如图所示:左边地图人员选定,右边表格相应选中. 功能代码: //表格和图标联动 function changeTableSel ...

  2. Bootstrap.css 中请求googleapis.com/css?family 备忘录

    问题描述: Web中引入bootstrap.css中头部有访问Google服务器的请求 @import url("//fonts.googleapis.com/css?family=Open ...

  3. 在Bootstrap开发框架中使用Grid++报表

    之前在随笔<在Winform开发中使用Grid++报表>介绍了在Winform环境中使用Grid++报表控件,本篇随笔介绍在Bootstrap开发框架中使用Grid++报表,也就是Web环 ...

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

    在前面随笔<在Bootstrap开发框架中使用dataTable直接录入表格行数据>中介绍了在Web页面中使用Jquery DataTable插件进行对数据直接录入操作,这种处理能够给用户 ...

  5. 在Bootstrap开发框架中使用dataTable直接录入表格行数据

    在Winform开发的时候,我们很多时候可以利用表格控件来直接录入数据,不过在Web上较少看到,其实也可以利用dataTable对象处理直接录入表格行数据,这个可以提高数据的录入方便,特别是在一些简单 ...

  6. 在Bootstrap开发框架中使用bootstrapTable表格插件和jstree树形列表插件时候,对树列表条件和查询条件的处理

    在我Boostrap框架中,很多地方需要使用bootstrapTable表格插件和jstree树形列表插件来共同构建一个比较常见的查询界面,bootstrapTable表格插件主要用来实现数据的分页和 ...

  7. 使用BootStrap框架中的轮播插件

    在使用bootstrap框架中的轮播插件时,效果做出来后,无法通过点击小圆行的按钮来选择特定的图片. 后面发现是最开始的<div>标签中少写了一个id.一开始<div>标签是这 ...

  8. 在Bootstrap框架中,form-control的效果

    在Bootstrap框架中,通过定制了一个类名`form-control`,也就是说,如果这几个元素使用了类名“form-control”,将会实现一些设计上的定制效果. 1.宽度变成了100% 2. ...

  9. bootstrap -- meta中的viewport指令

    在查看bootstrap教程中,碰到 <meta name="viewport" content="width=device-width, initial-scal ...

随机推荐

  1. bzoj 1005 1211 prufer序列总结

    两道题目大意都是根据每个点的度数来构建一棵无根树来确定有多少种构建方法 这里构建无根树要用到的是prufer序列的知识 先很无耻地抄袭了一段百度百科中的prufer序列的知识: 将树转化成Prufer ...

  2. Cordova android框架详解

    一.Cordova 核心java类说明 CordovaActivity:Cordova Activity入口,已实现PluginManager.WebView的相关初始化工作, 只需继承Cordova ...

  3. iOS 自定义emoji表情键盘

    之前走了很多弯路,包括自己定以emoji表情,自己创建view类去处理图文混排 ,当把这些焦头烂额的东西处理完了才发现 ,其实系统自带键盘是如此的方便,iOS 系统自带的表情在view,textfie ...

  4. Libgdx 开发指南(1) 应用框架

    应用框架 模块 Libgdx包含五个核心接口与操作系统交互,各自实现了如下接口: Application:运行应用,向client通知应用层事件,例如窗口大小的改变(window resizing). ...

  5. Error Handling

    Use Exceptions Rather Than Return Codes Back in the distant past there were many languages that didn ...

  6. css&js实现顶部banner滚动提示效果

    以一个小例子来展示滚动提示的代码部分: try.html <div id="scrollobj" > <span class="scrollTxt&qu ...

  7. Unity UGUI RectTransform图解

    UGUI RectTransform.Unity RectTransform详解 The first:look look API. http://docs.unity3d.com/ScriptRefe ...

  8. Javascript中call函数和apply函数的使用

    Javascript 中call函数和apply的使用: Javascript中的call函数和apply函数是对执行上下文进行切换,是将一个函数从当前执行的上下文切换到另一个对象中执行,例如: so ...

  9. vim编辑器使用相关

    alias 查看vi是否已经绑定vim 一.vim的块选择 v 字符选择 V 行选择 ctrl+v 快选择 y 复制选择的地方(p进行粘贴) d 删除选择的地方 二.vim多文件编辑 :n 编辑下一个 ...

  10. Notepad++配置Python开发环境

    1. 安装Python 1 下载 我选择了32位的2.7版本.https://www.python.org/ftp/python/2.7.8/python-2.7.8.msi 2. 安装 安装的时候可 ...