ElementUI 作为国内比较火的一个VUe框架,主要原因是其中的数组件满足了日常开发的大部分需求,在写Vue项目的时候,经常会用Alert 组件与用户进行交互。作为一名在Vue学习之路上的后生小辈,源码分析可以提高我们项目开发的意识,今天我就来解剖一下ElementUI 中的Alert组件,在分析它的源码之前,让我们先看看它完整的功能有哪些?ElementUI-Alert
看完Alert的参数,我们大概可以知道Alert 的一些功能,它可以设置主题,标题,类型,图标,居中效果,是否可关闭,关闭按钮自定义文本文本,关闭触发的事件。写下来我们就开始解剖Alert组件
Vue提供了封装的transition组件,在进入/离开的过程中,会产生6个类,通过6个类的样式切换可以实现简单的动画效果。具体可查阅官网
我们找到 node_modules 里找到element-ui/lib/theme-chalk/alert.css,其中涉及到transition的样式有
.el-alert-fade-enter, .el-alert-fade-leave-active { opacity: 0 } 复制代码
只是简单的改变透明度,没有其他的样式改变。
对于一般组件来说,组件的整体布局效果,都由外层盒子决定,这里也不意外,盒子的样式,以及居中效果都由这个div 决定
<div class="el-alert" :class="[typeClass, center ? 'is-center' : '', 'is-' + effect]" v-show="visible" role="alert" > 复制代码
这里的class 设置了盒子的默认样式,并且将一个数组绑定给力class,以应用此数组中的多个样式。现在然我们看看对应的一些参数
props: { type: { type: String, default: "info" }, center: Boolean, effect: { type: String, default: "light", validator: function(value) { return ["light", "dark"].indexOf(value) !== -1; } } }, data() { return { visible: true }; }, computed: { typeClass() { return `el-alert--${this.type}`; } } 复制代码
通过参数type 的值(success/warning/info/error),使用typeClass 计算属性计算出相应的类名,应用对应的样式。以及center,effect 属性,effect参数增加了validator 方法验证参数值,对于值的要求更为严格,若不在数组当中,不仅不会应用样式,还会报错。可以看到,到Alert 被调用是,visible的初始值就被赋予了true,对于role属性,在我们的日常开发中用的很少,role的作用是供有障碍的人士使用的,从这里可以看出一个好的框架应用的群体更加广泛。
i 标签的原作用本是改变文本样式,使文本斜体,但是由于在应用中非常少见,而图标的大量出现,使得i标签被icon 化。
<i class="el-alert__icon" :class="[ iconClass, isBigIcon ]" v-if="showIcon"></i> 复制代码
props: { showIcon: Boolean }, computed: { iconClass() { return TYPE_CLASSES_MAP[this.type] || "el-icon-info"; }, isBigIcon() { return this.description || this.$slots.default ? "is-big" : ""; } } 复制代码
<script> const TYPE_CLASSES_MAP = { 'success': 'el-icon-success', 'warning': 'el-icon-warning', 'error': 'el-icon-error' }; export default{ ... } </script> 复制代码
此处根据show-icon 的属性值,来判断是否需要渲染图标,当条件为真时,根据type属性的值计算得到相应类型的图标。计算图标方法中使用了逻辑或运算符,即从左往右运算开始,当出现第一个属性真值为true,则返回当前值,不再进行后续的逻辑运算。此种方法,将 el-icon-info
作为了默认图标。我们可以发现,只要我们开启了图标,即将show-icon 置为true,不论我们type 输入什么,图标等还是会出现,只是由于type的错误类型导致某些样式没有启用,而出现的视觉差异。isBigIcon 方法根据description的属性值或者插槽中的文本进行计算,当二者至少有一个为真时则渲染大图标。
.el-alert__content { display: table-cell; padding: 0 8px } 复制代码
此处渲染alert 框title的文本
<span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title"> <slot name="title">{{ title }}</slot> </span> 复制代码
props: { title: { type: String, default: "" } }, computed: { isBoldTitle() { return this.description || this.$slots.default ? 'is-bold' : ''; } } 复制代码
.el-alert__title { font-size : 13px; line-height: 18px } .el-alert__title.is-bold { font-weight: 700 } 复制代码
此处通过使用了$slots API ,来得到插槽中的值,从而确定title是否显示,当描述信息存在时,则标题为粗体。
<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> 复制代码
此处放置两个p 标签来渲染描述信息,在第一个p
标签中,含有一个不具名的 slot
插槽,此时插槽的默认名为 default
, 为当描述信息以插槽的形式出现时,描述信息渲染在当前插槽的位置,第二个为当描述信息以属性的方式在组件内部出现时,渲染组件的 description
参数值,然而,当组件内部和插槽中都出现了描述信息时,都不渲染描述信息。
<i class="el-alert__closebtn" :class="{ 'is-customed': closeText !== '', 'el-icon-close': closeText === '' }" v-show="closable" @click="close()">{{closeText}}</i> 复制代码
props: { closable: { type: Boolean, default: true }, closeText: { type: String, default: "" } }, methods: { close() { this.visible = false; this.$emit("close"); } } 复制代码
这里使用对象语法绑定class ,根据对象内属性的true or false 应用不同的css ,同时绑定了一个click
事件,使用close
方法将组件设为一种截然相反的状态,并且,在这个方法中$emit
这个API ,来达到关闭Alert
组件,触发与close
相绑定的事件行为。
作为一名刚上路的新手,第一眼看上去,感觉源码非常的复杂,但是,当仔细看进去了之后,发现其实也不难理解,通过源码的分析,我们不仅能够加深对Vue的理解,还能够帮助我们优化代码结构,培养业务能力。
萌新上路,请多多指教
如有错误,欢迎指出
饿了吗?有一说一,确实饿了。