3.16 Alert 警告

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结构渲染如下 👇: image.png

<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 Propertyvisible属性控制组件显示隐藏。组件虽为页面中的非浮层元素不会自动消失,但支持手动关闭隐藏。

  • role="alert" 表示当前元素的类型,用于 ARIA 无障碍访问设置。

根节点元素内部使用flex布局。两个子节点交叉轴的中点对齐。

is-center 通过设定属性justify-content 定义了主轴上的对齐方式,实现两个子节点水平居中。

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 不同大小尺寸效果 👇: image.png

3️⃣ 文字内容区域

该节点是一个class 名为el-alert__content<div> 元素,内容包含三个节点: 标题 4️⃣辅助性文字 5️⃣关闭按钮 6️⃣

文字内容区域 DOM 结构渲染如下 👇:

image.png

标题辅助性文字 节点提供了具名插槽和匿名插槽,分发内容时需要指明 slot#name,否则内容都会分发给匿名插槽。

4️⃣ 标题

该节点是一个class 名为el-alert__title<span> 元素,包裹着具名插槽 title

只有在 title属性值是 truthy 或者向该插槽分发内容时,该节点才会被渲染。title 是插槽的后备内容。若两者都设置了(传入title值而且向该插槽提供内容),渲染展示内容为插槽分发内容。

使用计算属性 isBoldTitle 动态添加样式。 isBoldTitle 根据辅助性文字内容是否设置,生成样式is-big 加粗title字体,用于区分与辅助性文字的主次。

5️⃣ 辅助性文字

该节点是一个class 名为el-alert__description<p>段落元素。该节点提供了匿名插槽或 description属性值,但是两者只能同时设置一项,才能正常显示。

当然可以改成如下逻辑,默认显示description属性值,插槽分发内容后优先显示后者。

基于很多组件的逻辑实现: prop属性大多作为插槽的后备内容, 暂时还不知为啥提供这么对立条件,有他无我!

6️⃣ 关闭按钮

节点默认是一个名为el-icon-close的Icon 图标,提供close事件来设置关闭时的回调。通过 closable属性决定是否可关闭。

若设置closeText属性值自定义关闭按钮,此时节点为包裹文本的 <i>元素。

关闭按钮位置偏移至右上角,样式el-alert__closebtn定义如下:

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],导致组件样式无法正常加载。

计算属性

typeClass

根据 type 属性值生成不同类型主题样式(背景颜色、文字颜色) el-alert-[success/warning/info/error]

iconClass

计算属性iconClass 根据 type 属性值生成不同类型 icon class el-icon-[success/warning/info/error]

若传入type值不是以下success/warning/error其中之一,都会生成el-icon-info,所以type默认值等于info

isBigIcon

根据辅助性文字内容是否设置,只有在 title属性值是 truthy 或者向该插槽分发内容时,生成样式is-big 加粗title字体,用于区分与辅助性文字的主次。

Icon 根据组件内容多少(高度也会调整),动态调整尺寸展示更加协调 👇: image.png

isBoldTitle

根据辅助性文字内容是否设置,只有在 title属性值是 truthy 或者向该插槽分发内容时,生成图标大尺寸样式is-big

close 事件

组件监听按钮的 click 事件 。当点击关闭按钮时,触发 click 事件,执行 close()方法,设置visible属性值 false,隐藏组件;调用 this.$emit('close') 触发当前实例上的close事件 。

0x02 组件样式

src/alert.scss

组件样式源码 packages\theme-chalk\src\alert.scss 使用混合指令 bemwhen 嵌套生成组件样式。

lib/alert.css

前文可知使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\alert.scss,内容格式如下。

0x03 📚参考

"ARIA",MDN

最后更新于