Element 2 组件源码剖析之Badge标记

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战css

0x00 简介

组件 Badge 通常和其它组件配合使用,用于进数字或状态标记提醒效果。vue

本文将深刻分析组件 Badge 源码,剖析其实现原理,耐心读完,相信会对您有所帮助。 组件文档 Badgenode

packages/badge/src/main.vue 文件是组件源码实现。 github源码 main.vuegit

0x01 template 模板

从模板内容看出,组件封装一个 <div> 元素,包含两项内容:github

  1. 提供了 slot ,没有设置后备内容(默认值);
  2. 使用了内置过渡动画的<sup>元素,用于定义上标文本。
<template>
  <div class="el-badge"> <slot></slot> <transition name="el-zoom-in-center"> <sup v-show="!hidden && (content || content === 0 || isDot)" v-text="content" class="el-badge__content" :class="[ 'el-badge__content--' + type, { 'is-fixed': $slots.default, 'is-dot': isDot } ]"> </sup> </transition> </div>
</template> 
复制代码

组件渲染后生成一个 class 值为 el-badge<div> 元素做为容器。slot 没有设置后备内容, 只有在组件包裹内容时才会进行渲染。生成一个 class 值为 el-badge__content<sup> 元素定义上标文本,用于实现数字或状态标记效果,使用内置组件 transition 实现缩放zoom-in-center效果。web

<sup> 的可见性由组件 prop hiddenisDot 和 计算属性content 进行控制。文本内容为content属性值。根据插槽传值$slots.defaulttypeisDot等属性值动态添加 class,实现不一样场景的形式展现。gulp

0x02 attributes 属性

组件提供了5个 prop浏览器

<script>
export default {
  name: 'ElBadge',

  props: {
    value: [String, Number], // 显示值
    max: Number, // 最大值,超过最大值会显示 '{max}+'
    isDot: Boolean, // 是否显示小圆点
    hidden: Boolean, // 是否隐藏 badge
    // 类型
    type: {
      type: String,
      validator(val) {
        return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
      }
    }
  },

  computed: {
    // 计算属性 上标显示内容 根据 isDot、value、max进行判断计算。
    content() {
      // ...
    }
  }
};
</script>
复制代码

属性描述

各属性功能描述以下:sass

参数 说明 类型 可选值 默认值
value 显示值 string, number
max 最大值,超过最大值会显示 '{max}+',要求 value 是 Number 类型 number
is-dot 小圆点 boolean false
hidden 隐藏 badge boolean false
type 类型 string primary / success / warning / danger / info

type 提供了 primary / success / warning / danger / info可选值,提供了自定义验证函数。markdown

// 自定义验证函数
type: { 
  validator(val) {
    // 这个值必须匹配下列字符串中的一个
    return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
  }
}
复制代码

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。 此时 type 值为undefined

image.png

计算属性

计算属性content值是上标显示内容。 根据 isDotvaluemax 等prop进行判断计算。

computed: {
    content() {
      // 小红点形式
      if (this.isDot) return;

      const value = this.value;
      const max = this.max;
      
      // 数值超过最大值处理
      if (typeof value === 'number' && typeof max === 'number') {
        return max < value ? `${max}+` : value;
      }

      return value;
    }
  }
复制代码

若使用小圆点形式, isDot 值为 true if (this.isDot) return;content值为 undefined

若不使用小圆点形式时,valueNumber 类型且设置了 max,判断是否超过最大值,超过会显示 {max}+,其他状况 content值等于 value值。

<sup>显隐逻辑

v-show 指令条件 !hidden && (content || content === 0 || isDot) 短路表达式是可知,若 hidden 值为true隐藏不显示,后续条件不执行。

若显示上标hidden 值为false,则继续根据显示内容 content是否存在内容进行判断, content === 0 逻辑是为了防止 当 value 为 0 时,表达式 (content) 返回 false。 使用圆点形式时,由上文可知contentundefinedisDot 值为true,此时表达式返回 true

动态class

根据 type 会动态的设置 el-badge__content--[type],用于不一样类型的上标颜色显示 el-badge__content--[primary/success/warning/danger/info]。当 type 未设置或者不是指定值时,class 值为el-badge__content--undefined

当组件和其它组件配合使用,包裹内容时提供给插槽值 $slots.default[Vnode],设置 is-fixed固定上标位置-右上角。

若使用小圆点形式时,设置is-dot控制上标的样式为红点。

0x03 组件样式

src/badge.scss

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

// 生成 el-badge
@include b(badge) {
  // ...
  
  // 生成 el-badge__content 
  @include e(content) {
    // ...
    
    // 生成 el-badge__content.is-fixed
    @include when(fixed) {
      // ...
      
      // 生成 el-badge__content.is-fixed.is-dot
      @include when(dot) {
        // ...
      }
    }
    
    // 生成 el-badge__content.is-fixed.is-dot
    @include when(dot) {
      // ...
    }

    @each $type in (primary, success, warning, info, danger) {
      // 生成 .el-badge__content--[primary/success/warning/info/danger]
      @include m($type) {
        // ...
      }
    }
  }
}

复制代码

lib/badge.scss

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

.el-badge {
  //...
}
.el-badge__content {
  //...
}
.el-badge__content.is-fixed {
  // ...
}
.el-badge__content.is-fixed.is-dot {
  // ...
}
.el-badge__content.is-dot {
  // ...
}
.el-badge__content--primary {
  background-color: #409eff;
}
.el-badge__content--success {
  background-color: #67c23a;
}
.el-badge__content--warning {
  background-color: #e6a23c;
}
.el-badge__content--info {
  background-color: #909399;
}
.el-badge__content--danger {
  background-color: #f56c6c;
}

复制代码

0x04 📚参考

"sass在线编辑器",sassmeister

0x05 关注专栏

此文章已收录到专栏中 👇,能够直接关注。