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. BaiduMap Search List

    using AnfleCrawler.Common; using HtmlClient; using System; using System.Collections.Generic; using S ...

  2. iOS6的旋屏控制技巧

    在iOS5.1 和 之前的版本中, 我们通常利用 shouldAutorotateToInterfaceOrientation: 来单独控制某个UIViewController的旋屏方向支持,比如: ...

  3. Java与数据库之间时间的处理

    Java与数据库之间时间的处理 在数据库中建表: DROP TABLE IF EXISTS `times`; CREATE TABLE `times` ( `id` int(11) NOT NULL ...

  4. 2016 - 1- 23 iOS中xml解析 (!!!!!!!有坑要解决!!!!!!)

    一: iOS中xml解析的几种方式简介 1.官方原生 NSXMLParser :SAX方式解析,使用起来比较简单 2.第三方框架 libxml2 :纯C 同时支持DOM与SAX GDataXML: D ...

  5. OpenCV是什么?

    OpenCV其实就是一对C和C++语言的源代码文件,这些源代码文件中实现了许多常用的计算机视觉算法.例如C借口函数cvCanny()实现了Canny边缘提取算法.可以直接将这些源代码添加到我们自己的项 ...

  6. C#中using关键字的作用及用法

    using的用途和使用技巧. 1.  引用命名空间 2.  为命名空间或类型创建别名 3.  使用using语句 1.  引用命名空间,这样可以在程序中引用命名空间的类型而不必指定详细的命名空间. a ...

  7. M3: 发送邮件附件(2)

    本小节介绍如何通过邮件将生成的贺卡发送给朋友.使用到了EmailMessageAPI, 需要引入的命名空间为Windows.ApplicationModel.Email. 请确保完成了以前的章节. 在 ...

  8. 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离。显示为公里、米

    /** * calc_map_distance() , 根据地图上的两个点各自的x,y坐标,计算出2点之间的直线距离 * @param array $point_1 第1个点的x,y坐标 array( ...

  9. LintCode Validate Binary Search Tree

    Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST) ...

  10. 初识Winform , 还好没喜欢上控制台

    虽然没听的太懂, 不过还是写点东西吧. 我呢, 就跟着这本书写了个学生管理系统 前面刚会了SQLserver, 所以这个学生管理系统需要连上数据库, 毕竟学了不用天诛地灭 既然需要连接数据库, 就要用 ...