这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
0x00 简介
组件 Alert
用于警告提示,展现需要关注的信息。本文将深入分析源码,剖析其实现原理,耐心读完,相信会对您有所帮助。组件源码实现详见packages/alert/src/main.vue
。 ? 组件文档 Alert ? gitee源码 main.vue
更多组件剖析详见 ? ? Element 2 源码剖析组件总览 。
0x01 组件源码
template 模板内容
组件模板创建一个class名为el-alert
的<div>
元素根节点 1️⃣
,包含两个子节点 :左侧的Icon图标``2️⃣
、右侧的文字内容区域
3️⃣
。 组件使用内置 transition
实现el-alert-fade
淡入淡出效果。
组件DOM结构渲染如下 ?:
<template>
<transition name="el-alert-fade">
<div
class="el-alert"
:class="[typeClass, center ? 'is-center' : '', 'is-' + effect]"
v-show="visible"
role="alert"
>
<!-- icon 图标 -->
<i class="el-alert__icon" :class="[ iconClass, isBigIcon ]" v-if="showIcon"></i>
<!-- 文字内容 包含关闭按钮 -->
<div class="el-alert__content">
<!-- 标题 -->
<span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title">
<slot name="title">{{ title }}</slot>
</span>
<!-- 辅助性文字介绍 -->
<p class="el-alert__description" v-if="$slots.default && !description"><slot></slot></p>
<p class="el-alert__description" v-if="description && !$slots.default">{{ description }}</p>
<!-- 关闭按钮 -->
<i class="el-alert__closebtn" :class="{ 'is-customed': closeText !== '',
'el-icon-close': closeText === '' }" v-show="closable" @click="close()">
{{closeText}}
</i>
</div>
</div>
</transition>
</template>
1️⃣ 根节点
-
根据传入prop的属性值动态添加class。
- 计算属性
typeClass
根据type
属性值生成不同类型样式 class ,el-alert--[success/warning/info/error]
。 - 根据
center
属性值生成is-center
,让图标文字水平居中。 - 根据
effect
属性值生成主题样式is-[light/dark]
。
- 计算属性
-
v-show="visible"
使用 Data Property 的visible
属性控制组件显示隐藏。组件虽为页面中的非浮层元素不会自动消失,但支持手动关闭隐藏。 -
role="alert"
表示当前元素的类型,用于ARIA
无障碍访问设置。
根节点元素内部使用flex布局。两个子节点交叉轴的中点对齐。
.el-alert {
display: flex;
/* 交叉轴的中点对齐 */
align-items: center;
}
is-center
通过设定属性justify-content
定义了主轴上的对齐方式,实现两个子节点水平居中。
.is-center {
justify-content: center;
}
2️⃣ Icon图标
该节点是一个Icon 图标元素,表示某种状态时提升可读性,图标节点是否渲染可见根据 showIcon
属性值决定 v-if="showIcon"
。
- 静态样式
el-alert__icon
定义图标默认尺寸。 - 使用计算属性
iconClass
isBigIcon
动态添加样式。- 计算属性
iconClass
根据type
属性值生成不同类型 icon class ,el-icon-[success/warning/info/error]
。 - 计算属性
isBigIcon
根据 辅助性文字内容是否设置,生成图标大尺寸样式is-big
。
- 计算属性
Icon 不同大小尺寸效果 ?:
3️⃣ 文字内容区域
该节点是一个class 名为el-alert__content
的<div>
元素,内容包含三个节点: 标题
4️⃣
、 辅助性文字
5️⃣
、 关闭按钮
6️⃣
。
文字内容区域 DOM 结构渲染如下 ?:
4️⃣ 标题
该节点是一个class 名为el-alert__title
的<span>
元素,包裹着具名插槽 title
。
只有在 title
属性值是 truthy
或者向该插槽分发内容时,该节点才会被渲染。title
是插槽的后备内容
。若两者都设置了(传入title
值而且向该插槽提供内容),渲染展示内容为插槽分发内容。
使用计算属性 isBoldTitle
动态添加样式。 isBoldTitle
根据辅助性文字内容是否设置,生成样式is-big
加粗title字体,用于区分与辅助性文字的主次。
.is-bold {
font-weight: 700;
}
5️⃣ 辅助性文字
该节点是一个class 名为el-alert__description
的<p>
段落元素。该节点提供了匿名插槽或 description
属性值,但是两者只能同时设置一项,才能正常显示。
当然可以改成如下逻辑,默认显示description
属性值,插槽分发内容后优先显示后者。
<p class="el-alert__description" v-if="description || $slots.default">
<slot> {{ description }} </slot>
</p>
6️⃣ 关闭按钮
节点默认是一个名为el-icon-close
的Icon 图标,提供close
事件来设置关闭时的回调。通过 closable
属性决定是否可关闭。
若设置closeText
属性值自定义关闭按钮,此时节点为包裹文本的 <i>
元素。
关闭按钮位置偏移至右上角,样式el-alert__closebtn
定义如下:
.el-alert__closebtn {
position: absolute;
top: 12px;
right: 15px;
}
attributes 属性
组件定义了8个prop 。
参数 | 说明 | 类型 | 可选值 | 默认值 | title | 标题 | string | — | — | type | 类型 | string | success/warning/info/error | info | description | 辅助性文字 | string | — | — | closable | 是否可关闭 | boolean | — | true | center | 文字是否居中 | boolean | — | true | close-text | 关闭按钮自定义文本 | string | — | — | show-icon | 是否显示图标 | boolean | — | false | effect | 选择提供的主题 | string | light/dark | light |
---|
effect
提供了自定义验证函数,提供了默认值light
。 若传入effect
值不是以下light/dark
其中之一,会生成无效的样式is-[effect]
,导致组件样式无法正常加载。
props: {
effect: {
type: String,
default: 'light',
validator: function(value) {
return ['light', 'dark'].indexOf(value) !== -1;
}
}
},
计算属性
typeClass
根据 type
属性值生成不同类型主题样式(背景颜色、文字颜色) el-alert-[success/warning/info/error]
。
computed: {
typeClass() {
return `el-alert--${ this.type }`;
},
}
iconClass
计算属性iconClass
根据 type
属性值生成不同类型 icon class el-icon-[success/warning/info/error]
。
const TYPE_CLASSES_MAP = {
'success': 'el-icon-success',
'warning': 'el-icon-warning',
'error': 'el-icon-error'
};
computed: {
iconClass() {
return TYPE_CLASSES_MAP[this.type] || 'el-icon-info';
},
}
若传入type
值不是以下success/warning/error
其中之一,都会生成el-icon-info
,所以type
默认值等于info
。
isBigIcon
根据辅助性文字内容是否设置,只有在 title
属性值是 truthy
或者向该插槽分发内容时,生成样式is-big
加粗title字体,用于区分与辅助性文字的主次。
computed: {
isBigIcon() {
return this.description || this.$slots.default ? 'is-big' : '';
},
}
Icon 根据组件内容多少(高度也会调整),动态调整尺寸展示更加协调 ?:
isBoldTitle
根据辅助性文字内容是否设置,只有在 title
属性值是 truthy
或者向该插槽分发内容时,生成图标大尺寸样式is-big
computed: {
isBoldTitle() {
return this.description || this.$slots.default ? 'is-bold' : '';
}
}
0x02 组件样式
src/alert.scss
组件样式源码 packages\theme-chalk\src\alert.scss
使用混合指令 b
、e
、m
、when
嵌套生成组件样式。
// .el-alert
@include b(alert) {
// ...
@include when(light) {
// .el-alert.is-light .el-alert__closebtn
.el-alert__closebtn { /* ... */ }
}
@include when(dark) {
// .el-alert.is-dark .el-alert__closebtn
.el-alert__closebtn { /* ... */ }
// .el-alert.is-dark .el-alert__description
.el-alert__description { /* ... */ }
}
// .el-alert.is-center
@include when(center) { /* ... */ }
// success warning error 格式类似
@include m(success) {
// .el-alert--success.is-light
&.is-light {
// ...
//.el-alert--success.is-light .el-alert__description
.el-alert__description { /* ... */ }
}
// .el-alert--success.is-dark
&.is-dark { /* ... */ }
}
// info
@include m(info) {
//.el-alert--info.is-light
&.is-light { /* ... */ }
// .el-alert--info.is-dark
&.is-dark { /* ... */ }
// .el-alert--info .el-alert__description
.el-alert__description { /* ... */ }
}
// .el-alert__content
@include e(content) { /* ... */ }
// .el-alert__icon
@include e(icon) {
// ...
// .el-alert__icon.is-big
@include when(big) { /* ... */ }
}
// .el-alert__title
@include e(title) {
// ...
// .el-alert__title.is-bold
@include when(bold) { /* ... */ }
}
// .el-alert .el-alert__description
& .el-alert__description { /* ... */ }
// .el-alert__closebtn
@include e(closebtn) {
// ...
// .el-alert__closebtn.is-customed
@include when(customed) { /* ... */ }
}
}
.el-alert-fade-enter, .el-alert-fade-leave-active { /* ... */ }
lib/alert.css
前文可知使用 gulpfile.js
编译 scss
文件转换为CSS
,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\alert.scss
,内容格式如下。
.el-alert { /* ... */ }
.el-alert.is-light .el-alert__closebtn { /* ... */ }
.el-alert.is-dark .el-alert__closebtn,
.el-alert.is-dark .el-alert__description { /* ... */ }
.el-alert.is-center { /* ... */ }
/* ...success... */
.el-alert--success.is-light { /* ... */ }
.el-alert--success.is-light .el-alert__description { /* ... */ }
.el-alert--success.is-dark { /* ... */ }
/* ...warning... */
/* ...error... */
/* ...info... */
.el-alert--info.is-light { /* ... */ }
.el-alert--info.is-dark { /* ... */ }
.el-alert--info .el-alert__description { /* ... */ }
.el-alert__content { /* ... */ }
.el-alert__icon { /* ... */ }
.el-alert__icon.is-big { /* ... */ }
.el-alert__title { /* ... */ }
.el-alert__title.is-bold { /* ... */ }
.el-alert .el-alert__description { /* ... */ }
.el-alert__closebtn { /* ... */ }
.el-alert__closebtn.is-customed { /* ... */ }
.el-alert-fade-enter, .el-alert-fade-leave-active { /* ... */ }
0x03 ?参考
"ARIA",MDN
0x04 关注专栏
此文章已收录到专栏中 ?,可以直接关注。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!