badge

5 阅读10分钟
<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="[
          type ? 'el-badge__content--' + type : null,
          {
            'is-fixed': $slots.default,
            'is-dot': isDot
          }
        ]">
      </sup>
    </transition>
  </div>
</template>

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

  props: {
    // 标记显示的数值或文本
    value: [String, Number],
    // 最大值,超过此值时显示为 "max+"
    max: Number,
    // 是否显示为小圆点
    isDot: Boolean,
    // 是否隐藏标记
    hidden: Boolean,
    // 标记类型,决定颜色样式
    type: {
      type: String,
      // 自定义验证器,只允许指定的类型值
      validator(val) {
        return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
      }
    }
  },

  computed: {
    // 计算标记显示的内容
    content() {
      // 如果是小圆点模式,不显示内容
      if (this.isDot) return;

      const value = this.value;
      const max = this.max;

      // 如果 value 和 max 都是数字类型
      if (typeof value === 'number' && typeof max === 'number') {
        // 超过最大值时显示 "max+",否则显示实际值
        return max < value ? `${max}+` : value;
      }

      // 直接返回 value(字符串或数字)
      return value;
    }
  }
};
</script>

Badge 组件教学文档

组件概述

Badge 是一个标记组件,用于在按钮、图标等元素上显示数字标记或状态标记。常用于显示通知数量、未读消息数、状态指示等场景。该组件支持数字标记、小圆点标记、自定义颜色和最大值限制等功能。


一、模板部分(Template)

1.1 容器元素

<div class="el-badge">

作用:组件的根容器,使用 el-badge 类名作为基础样式。

说明

  • 包裹整个组件的内容
  • 提供定位上下文
  • 作为样式钩子

1.2 默认插槽

<slot></slot>

作用:放置需要标记的元素。

说明

  • 使用默认插槽,允许父组件传入任意内容
  • 可以是按钮、图标、头像等任何元素
  • 标记会相对于这个元素进行定位

使用示例

<el-badge :value="12">
  <el-button>消息</el-button>
</el-badge>

<el-badge :value="5">
  <el-icon :size="20">
    <bell />
  </el-icon>
</el-badge>

1.3 过渡动画

<transition name="el-zoom-in-center">

作用:为标记添加缩放淡入动画效果。

原理

  • 使用 Vue 的内置过渡组件
  • el-zoom-in-center 类名实现从中心缩放淡入的效果
  • 当标记的显示状态变化时,自动应用动画

动画效果

  • 显示时:从中心放大并淡入
  • 隐藏时:缩小并淡出到中心

1.4 标记元素

<sup
  v-show="!hidden && (content || content === 0 || isDot)"
  v-text="content"
  class="el-badge__content"
  :class="[
    type ? 'el-badge__content--' + type : null,
    {
      'is-fixed': $slots.default,
      'is-dot': isDot
    }
  ]">
</sup>

详细解析

1.4.1 v-show 条件
v-show="!hidden && (content || content === 0 || isDot)"

作用:控制标记的显示/隐藏。

条件解析

  1. !hidden:未隐藏时才显示
  2. content:有内容时显示
  3. content === 0:内容为 0 时也显示(重要!)
  4. isDot:小圆点模式时显示

为什么需要 content === 0

  • 0 在 JavaScript 中是 falsy 值
  • 如果只写 content,值为 0 时会被隐藏
  • 但 0 是一个有效的数值,应该显示

示例

<!-- 显示:value=12 -->
<el-badge :value="12"></el-badge>

<!-- 显示:value=0 -->
<el-badge :value="0"></el-badge>

<!-- 隐藏:value="" -->
<el-badge :value=""></el-badge>

<!-- 隐藏:hidden=true -->
<el-badge :value="5" :hidden="true"></el-badge>
1.4.2 v-text 指令
v-text="content"

作用:设置标记的文本内容。

说明

  • 使用计算属性 content 的值
  • 相比 {{ }} 插值,v-text 性能更好
  • 避免 XSS 攻击(自动转义)
1.4.3 基础类名
class="el-badge__content"

作用:标记的基础样式类名。

样式包括

  • 背景色
  • 文字颜色
  • 圆角
  • 内边距
  • 字体大小
  • 定位方式
1.4.4 动态类名
:class="[
  type ? 'el-badge__content--' + type : null,
  {
    'is-fixed': $slots.default,
    'is-dot': isDot
  }
]"

类型类名

type ? 'el-badge__content--' + type : null

作用:根据 type 属性添加对应的颜色类名。

可能的类名

  • el-badge__content--primary:蓝色
  • el-badge__content--success:绿色
  • el-badge__content--warning:橙色
  • el-badge__content--info:灰色
  • el-badge__content--danger:红色

示例

<el-badge :value="5" type="primary"></el-badge>  <!-- 蓝色 -->
<el-badge :value="5" type="success"></el-badge>  <!-- 绿色 -->
<el-badge :value="5" type="danger"></el-badge>   <!-- 红色 -->

条件类名

{
  'is-fixed': $slots.default,
  'is-dot': isDot
}

is-fixed 类

  • 条件:$slots.default 存在
  • 作用:将标记固定在父元素的右上角
  • 效果:绝对定位,相对于父元素

is-dot 类

  • 条件:isDottrue
  • 作用:将标记显示为小圆点
  • 效果:圆形,无文字,固定大小

二、脚本部分(Script)

2.1 组件定义

export default {
  name: 'ElBadge',

作用:定义组件名称。

说明

  • 用于在 Vue DevTools 中识别组件
  • 便于调试和开发

2.2 Props 属性

2.2.1 value
value: [String, Number]

作用:标记显示的数值或文本。

类型

  • 字符串:可以显示文本,如 "NEW"、"HOT"
  • 数字:显示数字,如 12、99

使用示例

<!-- 显示数字 -->
<el-badge :value="12">
  <el-button>消息</el-button>
</el-badge>

<!-- 显示文本 -->
<el-badge value="NEW">
  <el-button>新品</el-button>
</el-badge>

注意事项

  • 空字符串 "" 会隐藏标记
  • 数字 0 会显示标记
  • 配合 max 属性使用时,必须是数字类型
2.2.2 max
max: Number

作用:设置最大值,超过此值时显示为 "max+"。

说明

  • 类型:数字
  • 可选属性
  • 只有当 value 也是数字类型时才生效

使用示例

<!-- 显示:5 -->
<el-badge :value="5" :max="99"></el-badge>

<!-- 显示:99+ -->
<el-badge :value="120" :max="99"></el-badge>

<!-- 显示:999+ -->
<el-badge :value="1500" :max="999"></el-badge>

应用场景

  • 通知数量:超过 99 显示 "99+"
  • 未读消息:超过 999 显示 "999+"
  • 避免数字过大影响布局
2.2.3 isDot
isDot: Boolean

作用:是否显示为小圆点。

说明

  • 类型:布尔值
  • 默认值:false
  • 设置为 true 时,标记显示为小圆点,不显示文字

使用示例

<!-- 显示小圆点 -->
<el-badge is-dot>
  <el-button>消息</el-button>
</el-badge>

<!-- 显示数字 -->
<el-badge :value="5">
  <el-button>消息</el-button>
</el-badge>

应用场景

  • 状态指示:有新消息时显示红点
  • 简洁设计:不需要显示具体数量
  • 移动端:节省空间

注意事项

  • isDottrue 时,valuemax 属性会被忽略
  • 小圆点有固定的大小和样式
2.2.4 hidden
hidden: Boolean

作用:是否隐藏标记。

说明

  • 类型:布尔值
  • 默认值:false
  • 设置为 true 时,完全隐藏标记

使用示例

<!-- 隐藏标记 -->
<el-badge :value="5" :hidden="true">
  <el-button>消息</el-button>
</el-badge>

<!-- 显示标记 -->
<el-badge :value="5" :hidden="false">
  <el-button>消息</el-button>
</el-badge>

应用场景

  • 条件显示:根据业务逻辑控制
  • 动态切换:用户可以关闭通知
  • 临时隐藏:不需要显示时

注意事项

  • 即使 value 有值,hiddentrue 也会隐藏
  • 可以通过动态绑定 :hidden 来控制显示状态
2.2.5 type
type: {
  type: String,
  validator(val) {
    return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
  }
}

作用:标记类型,决定颜色样式。

类型:字符串

可选值

  • primary:蓝色(主要)
  • success:绿色(成功)
  • warning:橙色(警告)
  • info:灰色(信息)
  • danger:红色(危险)

验证器

validator(val) {
  return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
}

作用

  • 自定义属性验证器
  • 确保只接受指定的类型值
  • 如果传入无效值,Vue 会发出警告

使用示例

<!-- 蓝色 -->
<el-badge :value="5" type="primary"></el-badge>

<!-- 绿色 -->
<el-badge :value="5" type="success"></el-badge>

<!-- 橙色 -->
<el-badge :value="5" type="warning"></el-badge>

<!-- 灰色 -->
<el-badge :value="5" type="info"></el-badge>

<!-- 红色 -->
<el-badge :value="5" type="danger"></el-badge>

应用场景

  • danger:未读消息、错误提示
  • success:成功数量、完成状态
  • warning:警告数量、待处理
  • info:信息数量、一般提示
  • primary:主要信息、重要通知

为什么需要验证器

  • 防止传入无效的类型值
  • 提供友好的错误提示
  • 确保组件样式的一致性

2.3 Computed 计算属性

2.3.1 content
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;
}

作用:计算标记显示的内容。

执行逻辑

  1. 小圆点模式

    if (this.isDot) return;
    
    • 如果是小圆点模式,直接返回 undefined
    • 不显示任何文字内容
  2. 获取属性值

    const value = this.value;
    const max = this.max;
    
  3. 数字类型判断

    if (typeof value === 'number' && typeof max === 'number') {
      return max < value ? `${max}+` : value;
    }
    
    • 如果 valuemax 都是数字类型
    • 判断是否超过最大值
    • 超过:显示 "max+"(如 "99+"
    • 未超过:显示实际值
  4. 默认返回

    return value;
    
    • 直接返回 value
    • 可以是字符串或数字

示例演示

valuemaxisDot显示内容
599false5
12099false99+
099false0
"NEW"99falseNEW
5-false5
599true(无内容)

为什么需要计算属性

  • 封装复杂的显示逻辑
  • 响应式更新:当 valuemaxisDot 变化时自动重新计算
  • 提高代码复用性
  • 使模板更简洁

性能优化

  • 计算属性有缓存
  • 只有依赖项变化时才重新计算
  • 避免不必要的重复计算

三、组件使用示例

3.1 基础用法

<template>
  <div>
    <el-badge :value="12">
      <el-button>消息</el-button>
    </el-badge>

    <el-badge :value="3">
      <el-button>评论</el-button>
    </el-badge>

    <el-badge :value="1">
      <el-button>回复</el-button>
    </el-badge>
  </div>
</template>

说明:最简单的用法,在按钮右上角显示数字标记。

3.2 最大值

<template>
  <div>
    <el-badge :value="200" :max="99">
      <el-button>消息</el-button>
    </el-badge>

    <el-badge :value="100" :max="10">
      <el-button>回复</el-button>
    </el-badge>
  </div>
</template>

说明:超过最大值时显示 "max+"。

3.3 自定义内容

<template>
  <div>
    <el-badge value="NEW">
      <el-button>新品</el-button>
    </el-badge>

    <el-badge value="HOT">
      <el-button>热门</el-button>
    </el-badge>

    <el-badge value="SALE">
      <el-button>促销</el-button>
    </el-badge>
  </div>
</template>

说明:使用字符串显示自定义文本。

3.4 小圆点

<template>
  <div>
    <el-badge is-dot>
      <el-button>消息</el-button>
    </el-badge>

    <el-badge is-dot>
      <el-icon :size="20">
        <bell />
      </el-icon>
    </el-badge>
  </div>
</template>

说明:显示小圆点,不显示数字。

3.5 不同类型

<template>
  <div>
    <el-badge :value="12" type="primary">
      <el-button>主要</el-button>
    </el-badge>

    <el-badge :value="3" type="success">
      <el-button>成功</el-button>
    </el-badge>

    <el-badge :value="5" type="warning">
      <el-button>警告</el-button>
    </el-badge>

    <el-badge :value="8" type="info">
      <el-button>信息</el-button>
    </el-badge>

    <el-badge :value="1" type="danger">
      <el-button>危险</el-button>
    </el-badge>
  </div>
</template>

说明:使用不同的颜色类型。

3.6 隐藏标记

<template>
  <div>
    <el-badge :value="12" :hidden="true">
      <el-button>消息</el-button>
    </el-badge>

    <el-badge :value="12" :hidden="showBadge">
      <el-button>消息</el-button>
    </el-badge>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showBadge: false
    }
  }
}
</script>

说明:通过 hidden 属性控制标记的显示/隐藏。

3.7 配合图标使用

<template>
  <div>
    <el-badge :value="5">
      <el-icon :size="24">
        <bell />
      </el-icon>
    </el-badge>

    <el-badge :value="3" is-dot>
      <el-icon :size="24">
        <message />
      </el-icon>
    </el-badge>
  </div>
</template>

说明:在图标上显示标记。

3.8 配合头像使用

<template>
  <div>
    <el-badge :value="2" is-dot>
      <el-avatar :size="40" src="user.jpg"></el-avatar>
    </el-badge>
  </div>
</template>

说明:在头像上显示状态标记。

3.9 动态更新

<template>
  <div>
    <el-badge :value="messageCount" :max="99">
      <el-button @click="addMessage">消息</el-button>
    </el-badge>

    <el-button @click="clearMessage">清空</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      messageCount: 0
    }
  },
  methods: {
    addMessage() {
      this.messageCount++;
    },
    clearMessage() {
      this.messageCount = 0;
    }
  }
}
</script>

说明:动态更新标记的数值。

3.10 组合使用

<template>
  <div>
    <!-- 小圆点 + 危险类型 -->
    <el-badge is-dot type="danger">
      <el-button>紧急消息</el-button>
    </el-badge>

    <!-- 最大值 + 成功类型 -->
    <el-badge :value="150" :max="99" type="success">
      <el-button>已完成</el-button>
    </el-badge>

    <!-- 自定义文本 + 警告类型 -->
    <el-badge value="NEW" type="warning">
      <el-button>新品</el-button>
    </el-badge>
  </div>
</template>

说明:组合使用多个属性。


四、核心知识点总结

4.1 Vue 组件开发

  1. 插槽(Slot)

    • 默认插槽的使用
    • 灵活的内容分发
    • $slots.default 检测插槽内容
  2. Props 定义

    • 类型检查:[String, Number]
    • 默认值:default: 200
    • 自定义验证器:validator
    • 布尔值简写:isDot: Boolean
  3. 计算属性(Computed)

    • 封装复杂逻辑
    • 自动缓存
    • 响应式更新
  4. 条件渲染

    • v-show:切换显示/隐藏
    • 复杂条件表达式
    • 注意 falsy 值的处理
  5. 动态类名

    • 数组语法
    • 对象语法
    • 条件类名

4.2 过渡动画

  1. Transition 组件

    • 内置过渡组件
    • 自动添加/移除 CSS 类
    • 配合 CSS 实现动画效果
  2. 动画类型

    • el-zoom-in-center:缩放淡入
    • el-fade-in:淡入淡出

4.3 样式设计

  1. 定位方式

    • is-fixed:绝对定位
    • 相对于父元素定位
    • 右上角固定位置
  2. 颜色系统

    • 语义化颜色
    • primary、success、warning、info、danger
    • 统一的设计语言
  3. 响应式设计

    • 适配不同屏幕尺寸
    • 保持视觉一致性

4.4 用户体验

  1. 视觉反馈

    • 动画过渡
    • 平滑显示/隐藏
    • 吸引用户注意
  2. 信息层次

    • 数字标记:显示具体数量
    • 小圆点:简洁的状态指示
    • 最大值限制:避免信息过载
  3. 灵活配置

    • 多种显示模式
    • 可自定义颜色
    • 可控制显示/隐藏

4.5 最佳实践

  1. 属性验证

    • 使用 validator 验证属性值
    • 提供友好的错误提示
    • 确保组件的健壮性
  2. 性能优化

    • 使用计算属性缓存结果
    • 避免不必要的计算
    • 使用 v-show 而非 v-if(频繁切换时)
  3. 代码可读性

    • 清晰的命名
    • 合理的注释
    • 逻辑分层

五、常见问题

5.1 为什么 value 为 0 时不显示?

原因

  • 0 在 JavaScript 中是 falsy 值
  • 如果条件是 v-show="content",0 会被隐藏

解决方法

v-show="!hidden && (content || content === 0 || isDot)"
  • 明确判断 content === 0
  • 确保 0 也能显示

5.2 如何自定义标记的位置?

方法:通过 CSS 覆盖默认样式。

<template>
  <el-badge :value="5" class="custom-badge">
    <el-button>消息</el-button>
  </el-badge>
</template>

<style>
.custom-badge .el-badge__content {
  top: -10px;
  right: -10px;
}
</style>

5.3 如何自定义标记的颜色?

方法 1:使用 type 属性

<el-badge :value="5" type="danger"></el-badge>

方法 2:通过 CSS 覆盖

<template>
  <el-badge :value="5" class="custom-color">
    <el-button>消息</el-button>
  </el-badge>
</template>

<style>
.custom-color .el-badge__content {
  background-color: #ff6b6b;
}
</style>

5.4 为什么 max 不生效?

原因

  • value 不是数字类型
  • max 不是数字类型
  • 两者必须都是数字类型

解决方法

<!-- 正确:都是数字 -->
<el-badge :value="120" :max="99"></el-badge>

<!-- 错误:value 是字符串 -->
<el-badge value="120" :max="99"></el-badge>

<!-- 错误:max 是字符串 -->
<el-badge :value="120" max="99"></el-badge>

5.5 如何实现动态更新标记?

方法:使用响应式数据。

<template>
  <el-badge :value="count">
    <el-button>消息</el-button>
  </el-badge>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  mounted() {
    // 模拟接收新消息
    setInterval(() => {
      this.count++;
    }, 5000);
  }
}
</script>

5.6 如何在多个元素上使用标记?

方法:为每个元素单独包裹 el-badge

<template>
  <div>
    <el-badge :value="5">
      <el-button>消息</el-button>
    </el-badge>

    <el-badge :value="3">
      <el-button>评论</el-button>
    </el-badge>

    <el-badge :value="1">
      <el-button>回复</el-button>
    </el-badge>
  </div>
</template>

六、扩展建议

6.1 功能扩展

  1. 自定义动画:添加 animation 属性
  2. 点击事件:添加 @click 事件
  3. 自定义位置:添加 position 属性(top-right、top-left、bottom-right、bottom-left)
  4. 自定义大小:添加 size 属性(small、medium、large)
  5. 自定义图标:在小圆点中显示图标

6.2 样式扩展

  1. 渐变背景:支持渐变色
  2. 边框样式:添加边框选项
  3. 阴影效果:添加阴影样式
  4. 自定义形状:方形、圆形、胶囊形
  5. 自定义字体:字体大小、字体粗细

6.3 交互扩展

  1. 悬停提示:添加 Tooltip
  2. 点击跳转:点击标记跳转到指定页面
  3. 长按操作:长按显示详细信息
  4. 拖拽功能:拖拽标记到其他位置
  5. 动画效果:更多动画选项

七、与其他组件的配合

7.1 配合 Button 组件

<el-badge :value="12">
  <el-button type="primary">消息</el-button>
</el-badge>

7.2 配合 Icon 组件

<el-badge :value="5" is-dot>
  <el-icon :size="24">
    <bell />
  </el-icon>
</el-badge>

7.3 配合 Avatar 组件

<el-badge :value="2" is-dot>
  <el-avatar :size="40" src="user.jpg"></el-avatar>
</el-badge>

7.4 配合 Card 组件

<el-badge :value="5" type="danger">
  <el-card>
    卡片内容
  </el-card>
</el-badge>

7.5 配合 Menu 组件

<el-menu>
  <el-menu-item>
    <el-badge :value="12">
      <span>消息</span>
    </el-badge>
  </el-menu-item>
</el-menu>

八、总结

ElBadge 是一个简单但功能强大的标记组件。通过学习这个组件,我们掌握了:

  1. Vue 组件基础:Props、插槽、计算属性、条件渲染
  2. 动态类名:灵活的样式绑定方式
  3. 过渡动画:使用 Transition 组件实现动画效果
  4. 属性验证:使用 validator 确保属性值的正确性
  5. 用户体验设计:信息层次、视觉反馈、灵活配置

这个组件虽然代码量不大,但包含了 Vue 组件开发的许多核心概念,是学习组件开发的优秀示例。它的设计思路和实现方式可以应用到其他类似的组件中。