认识Bootstrap之前
- 这里下载的是Bootstrap v4.0 dev 版本
- css预处理器使用了sass
- js使用了es6
- Bootstrap是依赖于Jquery的,其所有javascript组件都是注册在jquery原型上的,即一般组件末尾会有如下代码:
$.fn.xxx = Plugin
,也即jQuery.prototype.xxx = Plugin
- 如果在jQuery中定义了与Bootstrap组件同名的组件(没必要同名吧?),那么可以调用
$.fn.xxx.noConflict
来覆盖Bootstrap中的组件。
Alert(警告框)组件
一、简介
此组件应该是bootstrap中最简单的组件了,代码量较少,所以优先了解。此组件常见于为用户操作提供反馈信息,比如登陆密码错误,没有操作权限等简单提示。
二、样式
- 警告框必须有
alert
类 - 分别有四种配色:
alert-success
,alert-info
,alert-warning
,alert-danger
- 警告框里也可以美化链接样式: 对a标签添加
alert-link
类即可
三、脚本(可选)
为警告框添加关闭按钮,让用户有更好的体验。
从代码中提取整个组件的轮廓:
class Alert {
// 点击关闭按钮时真正触发的函数
close(ele) {}
// $('xxx').alert()触发
static _jQueryInterface(config) {
// 使用jquery的data api为控制元素绑定alert实例
// if config is 'close': trigger('close')
}
// 用于事件委托
static _handleDismiss(alertInstance) {
return function (event) {
// preventDefault
// alertInstance.close(this)
}
}
}
// 采用事件委托的方式为元素添加事件,便于元素的移除与添加
$(document).on(
Event.CLICK_DATA_API, // click.bs.alert.data-api
Selector.DISMISS, // '[data-dismiss="alert"]'
Alert._handleDismiss(new Alert())
)
上述代码表示,可以通过两种方式触发Alert的close函数:
- jQuery的事件委托,当点击
document
时,若event.target
为$('[data-dismiss="alert"]')
元素,即调用_handleDismiss
事件触发最终的close
函数。 - 通过js直接调用,即
$('xxx').alert('close')
通过_jQueryInterface
触发最终的close
函数
以上提及的两点也是实现警告框关闭的两种方式。
使用细节
Bootstrap提供了close的样式:
.alert-dismissible {
// Adjust close link position
.close {
position: relative;
top: -$alert-padding-y;
right: -$alert-padding-x;
padding: $alert-padding-y $alert-padding-x;
color: inherit;
}
}
可见,如果要用botostrap提供的关闭按钮样式(按钮出现在警告框右上角),必须在父元素上添加 alert-dismissible
类。
之前提及的 close
函数是整个组件的核心函数,目的是在dom中移除警告框,触发用户自定义事件。函数执行流程:
获取要关闭的警告框元素(_getRootElement),以下选择器都是取匹配的第一个元素
- 在关闭标签(
button
或是a
)上指定data-target
,值为一个选择器 - 若是
a
标签,可以指定href
为一个选择器,必须是id选择器 - 以上都没有,则为关闭元素最近的带
alert
类的祖宗元素, ($(‘xxx’).closest(‘.alert’))
- 在关闭标签(
触发真正关闭警告框前调用的钩子:
close.bs.alert
; 可以在该钩子中调用preventDefault
,阻止警告框关闭- 移除
show
类,即让元素的opacity
为0
- 若想要动画效果,必须要为警告框同时添加
.fade.show
两个类 - 浏览器不支持动画则无效
- 若想要动画效果,必须要为警告框同时添加
- 移除元素,触发警告框关闭后的钩子:
closed.bs.alert
;
- 调用
$.detach
移除元素(但事件仍可触发) - $.trigger(‘closed.bs.alert’)
- 调用
$.remove
完全移除元素
- 调用
简单改造
根据上面描述的 close
函数的执行过程,可以发现此组件不便于重复利用。虽然jquery中remove的元素依旧存在,但我们却难以获取到。所以这里我对此组件进行简单的改造,使用 display
属性保证组件的可重复利用(缺陷:display属性从 none
至其他,不会有任何动画)。
下面是新添加的 show
函数:
show(element){
// 与close函数其实并无太大区别,依旧是先获取警告框元素
element = element || this._element
const rootElement = this._getRootElement(element)
// 事件添加与close无区别,这里不提
// const customEvent = this._triggerShowEvent(rootElement)
if($(rootElement).hasClass(ClassName.SHOW)){
throw new Error('already show')
}
if (customEvent.isDefaultPrevented()) {
return
}
this._showElement(rootElement)
}
_showElement(element) {
// 根据之前对close流程的描述,可以知道只有再fade和show类同时存在时警告框元素才会显现,现在恢复show类
$(element).addClass(ClassName.SHOW)
if (!Util.supportsTransitionEnd() ||
!$(element).hasClass(ClassName.FADE)) {
this._recoverElement(element)
return
}
$(element)
.one(Util.TRANSITION_END, (event) => this._recoverElement(element, event))
.emulateTransitionEnd(TRANSITION_DURATION)
}
// 事件不提,只需要改变元素display属性即可
_recoverElement(element) {
// $(element)
// .detach()
// .trigger(Event.CLOSED)
// .remove()
$(element).show()
}
上面是添加了 show
函数,调用方式与close一致:
// 这里要注意一下,根据上面close流程的分析,发现触发下面alert事件的元素应该是警告框的关闭按钮元素,而非警告框元素(如果使用了警告框元素触发,也能通过js将该警告框删除,但是如果按钮有data-target这样做就忽略了这个属性的作用,虽然这个按钮本身就是用于关闭警告框)
$('').alert('show')
既然选择了将警告框隐藏而非删除,那么为document绑定的 Event.CLICK_DATA_API
事件触发的函数就不用每次 new 一个 Alert 实例了。修改如下:
$(document).on(
Event.CLICK_DATA_API,
Selector.DISMISS,
Alert._handleDismiss()
)
// 此时_handleDismiss修改如下
static _handleDismiss(event){
if(event){
event.preventDefault()
}
// 将生成的实例绑定元素
Alert._jQueryInterface.call($(this))
const data = $(this).data(DATA_KEY)
data.close()
}
这样就实现了警告框的close和show函数,可以重复利用。