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. linux shell 指令 诸如-d, -f, -e之类的判断表达式

    文件比较运算符-e filename 如果 filename存在,则为真 [ -e /var/log/syslog ]-d filename 如果 filename为目录,则为真 [ -d /tmp/ ...

  2. Android通过HttpURLConnection链接到网络,并获取网络数据

    1.判断网络是否连接 private void networkIsconnected(String str){ ConnectivityManager connMgr = (ConnectivityM ...

  3. javascript高级教程:如何优化javascript代码性能

    在web前端开发中,为实现一些动态效果,减小页面大小,我们一般都会使用JavaScript技术来进行相关设置.但是初学者在编写JavaScript代码的时候,往往都是比较低质的代码,那如何才能提高Ja ...

  4. poj3660 floyd

    //Accepted 176 KB 16 ms //一头牛,如果rank是能确定的,那么能打败他的牛的个数和被他打败的牛的个数的总和为n-1 #include <cstdio> #incl ...

  5. 网页版电子表格控件tmlxSpreadsheet免费下载地址

    tmlxSpreadsheet 是一个由JavaScript 和 PHP 写成的电子表格控件(包含WP插件, Joomla插件等等).. 程序员可以容易的添加一个类似Excel功能的,可编辑的表格功能 ...

  6. HDU 5838 (状压DP+容斥)

    Problem Mountain 题目大意 给定一张n*m的地图,由 . 和 X 组成.要求给每个点一个1~n*m的数字(每个点不同),使得编号为X的点小于其周围的点,编号为.的点至少大于一个其周围的 ...

  7. PAT (Basic Level) Practise:1028. 人口普查

    [题目链接] 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过200岁的老人,而今天是 ...

  8. 讨论贴:在sp_executesql 中生成的临时表的可见性

    首先创建数据表 IF object_id('TestTable') IS NOT NULL DROP TABLE TestTable GO ,),Info )) GO INSERT TestTable ...

  9. Jena TDB assembler syntax

    1 introduction Assembler is a DSL of Jena to specify something to build, models and dataset, for exa ...

  10. linux下oracle 10g的sqlplus无法使用

    问题如标题所示. 解决办法, 1,root用户登录,建立软连接 cd / cd /usr/bin ln -s /home/oracle/product/10.2.0/db_1/bin/sqlplus ...