Vue3徽标数(Badge)

APIs

参数说明类型默认值必传
color自定义小圆点的颜色string‘’false
count展示的数字,大于 overflowCount 时显示为 overflowCount+,为 0 时隐藏number | slot0false
overflowCount展示封顶的数字值number99false
showZero当数值为 0 时,是否展示 Badgebooleanfalsefalse
dot不展示数字,只有一个小红点booleanfalsefalse
status设置 Badge 为状态点‘success’ | 'processing | ‘default’ | ‘error’ | ‘warn’undefinedfalse
text在设置了 status 的前提下有效,设置状态点的文本string | slot‘’false
numberStyle设置状态点的样式CSSProperties{}false
title设置鼠标放在状态点上时显示的文字string‘’false
ripple是否开启涟漪动画效果booleantruefalse

效果如下图:在线预览

在这里插入图片描述
在这里插入图片描述

创建徽标数组件Badge.vue

<script setup lang="ts">
import type { CSSProperties } from 'vue'
import { ref, computed, onMounted } from 'vue'
enum Status {
  success = 'success',
  process = 'processing',
  default = 'default',
  error = 'error',
  warn = 'warn'
}
interface Props {
  color?: string // 自定义小圆点的颜色
  count?: number // 展示的数字,大于 overflowCount 时显示为 overflowCount+,为 0 时隐藏;number | slot
  overflowCount?: number // 展示封顶的数字值
  showZero?: boolean // 当数值为 0 时,是否展示 Badge
  dot?: boolean // 不展示数字,只有一个小红点
  status?: Status // 设置 Badge 为状态点
  text?: string // 在设置了 status 的前提下有效,设置状态点的文本 string | slot
  numberStyle?: CSSProperties // 设置状态点的样式
  title?: string // 设置鼠标放在状态点上时显示的文字
  ripple?: boolean // 是否开启涟漪动画效果
}
const props = withDefaults(defineProps<Props>(), {
  color: '',
  count: 0,
  overflowCount: 99,
  showZero: false,
  dot: false,
  status: undefined,
  text: '',
  numberStyle: () => ({}),
  title: '',
  ripple: true
})
const presetColor = ['pink', 'red', 'yellow', 'orange', 'cyan', 'green', 'blue', 'purple', 'geekblue', 'magenta', 'volcano', 'gold', 'lime']
const customStyle = computed(() => {
  if (props.color && !presetColor.includes(props.color)) {
    return {
      color: props.color,
      backgroundColor: props.color
    } 
  }
})
const contentRef = ref()
const showContent = ref(1)
const countRef = ref()
const showCount = ref(1)
onMounted(() => {
  if (!props.status && !props.color) {
    showContent.value = contentRef.value.offsetHeight
    showCount.value = countRef.value.offsetHeight
  }
})
</script>
<template>
  <div class="m-badge" :class="{'badge-status': status}">
    <template v-if="status||color">
      <span class="u-status-dot" :class="[`status-${status||color}`, {'dot-ripple': ripple}]" :style="customStyle"></span>
      <span class="u-status-text">
        <slot>{{ text }}</slot>
      </span>
    </template>
    <template v-else>
      <span ref="contentRef" v-if="showContent">
        <slot></slot>
      </span>
      <span
        ref="countRef"
        v-if="showCount"
        class="m-count"
        :class="{'only-number': !showContent}">
        <slot name="count"></slot>
      </span>
      <Transition name="zoom" v-else>
        <div
          v-show="showZero || count !== 0 || dot"
          class="m-badge-count"
          :class="{'small-num': count < 10, 'only-number': !showContent, 'only-dot': count === 0 && !showZero}"
          :style="numberStyle"
          :title="title || String(count)">
          <span v-if="!dot" class="m-number" style="transition: none 0s ease 0s;">
            <span class="u-number">{{ count > overflowCount ? overflowCount + '+' : count }}</span>
          </span>
        </div>
      </Transition>
    </template>
  </div>
</template>
<style lang="less" scoped>
.zoom-enter-active {
  animation: zoomBadgeIn .3s cubic-bezier(0.12, 0.4, 0.29, 1.46);
  animation-fill-mode: both;
}
.zoom-leave-active {
  animation: zoomBadgeOut .3s cubic-bezier(0.12, 0.4, 0.29, 1.46);
  animation-fill-mode: both;
}
@keyframes zoomBadgeIn {
  0% {
    transform: scale(0) translate(50%, -50%);
    opacity: 0;
  }
  100% {
    transform: scale(1) translate(50%, -50%);
  }
}
@keyframes zoomBadgeOut {
  0% {
    transform: scale(1) translate(50%, -50%);
  }
  100% {
    transform: scale(0) translate(50%, -50%);
    opacity: 0;
  }
}
.m-badge {
  color: rgba(0, 0, 0, .88);
  font-size: 14px;
  line-height: 1;
  position: relative;
  display: inline-block;
  width: fit-content;
  .u-status-dot {
    position: relative;
    top: -1px;
    display: inline-block;
    width: 6px;
    height: 6px;
    vertical-align: middle;
    border-radius: 50%;
  }
  .dot-ripple {
    &::after {
      box-sizing: border-box;
      position: absolute;
      top: 0;
      inset-inline-start: 0;
      width: 100%;
      height: 100%;
      border-width: 1px;
      border-style: solid;
      border-color: inherit;
      border-radius: 50%;
      animation-name: dotRipple;
      animation-duration: 1.2s;
      animation-iteration-count: infinite;
      animation-timing-function: ease-in-out;
      content: "";
    }
    @keyframes dotRipple {
      0% {
        transform: scale(.8);
        opacity: .5;
      }
      100% {
        transform: scale(2.4);
        opacity: 0;
      }
    }
  }
  .status-success {
    color: #52c41a;
    background-color: #52c41a;
  }
  .status-error {
    color: #ff4d4f;
    background-color: #ff4d4f;
  }
  .status-default {
    color: rgba(0, 0, 0, .25);
    background-color: rgba(0, 0, 0, .25);
  }
  .status-processing {
    color: #1677ff;
    background-color: #1677ff;
  }
  .status-warn {
    color: #faad14;
    background-color: #faad14;
  }
  .status-pink {
    color: #eb2f96;
    background-color: #eb2f96;;
  }
  .status-red {
    color: #f5222d;
    background-color: #f5222d;
  }
  .status-yellow {
    color: #fadb14;
    background-color: #fadb14;
  }
  .status-orange {
    color: #fa8c16;
    background-color: #fa8c16;
  }
  .status-cyan {
    color: #13c2c2;
    background-color: #13c2c2;
  }
  .status-green {
    color: #52c41a;
    background-color: #52c41a;
  }
  .status-blue {
    color: #1677ff;
    background-color: #1677ff;
  }
  .status-purple {
    color: #722ed1;
    background-color: #722ed1;
  }
  .status-geekblue {
    color: #2f54eb;
    background-color: #2f54eb;
  }
  .status-magenta {
    color: #eb2f96;
    background-color: #eb2f96;
  }
  .status-volcano {
    color: #fa541c;
    background-color: #fa541c;
  }
  .status-gold {
    color: #faad14;
    background-color: #faad14;
  }
  .status-lime {
    color: #a0d911;
    background-color: #a0d911;
  }
  .u-status-text {
    margin-inline-start: 8px;
    color: rgba(0, 0, 0, .88);
    font-size: 14px;
  }
  .m-count {
    position: absolute;
    top: 0;
    inset-inline-end: 0;
    transform: translate(50%, -50%);
    transform-origin: 100% 0%;
  }
  .m-badge-count {
    .m-count();
    overflow: hidden;
    padding: 0 8px;
    z-index: auto;
    min-width: 20px;
    height: 20px;
    color: #ffffff;
    font-weight: normal;
    font-size: 12px;
    line-height: 20px;
    white-space: nowrap;
    text-align: center;
    background: #ff4d4f;
    border-radius: 10px;
    box-shadow: 0 0 0 1px #ffffff;
    transition: background .2s;
    .m-number {
      position: relative;
      display: inline-block;
      height: 20px;
      transition: all .3s cubic-bezier(0.12, 0.4, 0.29, 1.46);
      -webkit-transform-style: preserve-3d; // 设置元素的子元素是位于 3D 空间中还是平面中 flat | preserve-3d
      -webkit-backface-visibility: hidden; // 当元素背面朝向观察者时是否可见 hidden | visible
      .u-number {
        display: inline-block;
        height: 20px;
        margin: 0;
        -webkit-transform-style: preserve-3d;
        -webkit-backface-visibility: hidden;
      }
    }
  }
  .small-num {
    padding: 0;
  }
  .only-number {
    position: relative;
    top: auto;
    display: block;
    transform-origin: 50% 50%;
    transform: none;
  }
  .only-dot {
    z-index: auto;
    width: 6px;
    min-width: 6px;
    height: 6px;
    background: #ff4d4f;
    border-radius: 100%;
    box-shadow: 0 0 0 1px #ffffff;
    padding: 0;
    transition: background .3s;
  }
}
.badge-status {
  line-height: inherit;
  vertical-align: baseline;
}
</style>

在要使用的页面引入

其中引入使用了 Vue3间距(Space)

<script setup lang="ts">
import Badge from './Badge.vue'
import { ref } from 'vue'
const show = ref(true)
const colors = [
  'pink',
  'red',
  'yellow',
  'orange',
  'cyan',
  'green',
  'blue',
  'purple',
  'geekblue',
  'magenta',
  'volcano',
  'gold',
  'lime',
]
</script>
<template>
  <div>
    <h1>Badge 徽标数</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Space :size="20">
      <Badge :count="5">
        <span class="u-cube"></span>
      </Badge>
      <Badge :count="0" show-zero>
        <span class="u-cube"></span>
      </Badge>
      <Badge>
        <template #count>
          <svg focusable="false" class="u-svg" data-icon="clock-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M686.7 638.6L544.1 535.5V288c0-4.4-3.6-8-8-8H488c-4.4 0-8 3.6-8 8v275.4c0 2.6 1.2 5 3.3 6.5l165.4 120.6c3.6 2.6 8.6 1.8 11.2-1.7l28.6-39c2.6-3.7 1.8-8.7-1.8-11.2z"></path></svg>
        </template>
        <span class="u-cube"></span>
      </Badge>
    </Space>
    <h2 class="mt30 mb10">独立使用</h2>
    <Space :size="20">
      <Badge :count="25" />
      <Badge
        :count="4"
        :number-style="{
          backgroundColor: '#fff',
          color: '#999',
          boxShadow: '0 0 0 1px #d9d9d9 inset',
        }"
      />
      <Badge :count="109" :number-style="{ backgroundColor: '#52c41a' }" />
    </Space>
    <h2 class="mt30 mb10">封顶数字</h2>
    <Space :size="30">
      <Badge :count="99">
        <span class="u-cube"></span>
      </Badge>
      <Badge :count="100">
        <span class="u-cube"></span>
      </Badge>
      <Badge :count="99" :overflow-count="10">
        <span class="u-cube"></span>
      </Badge>
      <Badge :count="1000" :overflow-count="999">
        <span class="u-cube"></span>
      </Badge>
    </Space>
    <h2 class="mt30 mb10">小红点</h2>
    <Badge dot>
      <a href="#">Link something</a>
    </Badge>
    <h2 class="mt30 mb10">状态点</h2>
    <Space :size="10">
      <Badge status="success" />
      <Badge status="error" />
      <Badge status="default" />
      <Badge status="processing" />
      <Badge status="warn" />
    </Space>
    <br/>
    <Space style="margin-top: 10px;" direction="vertical" :size="10">
      <Badge status="success" text="Success" />
      <Badge status="error" text="Error" />
      <Badge status="default" text="Default" />
      <Badge status="processing" text="Processing" />
      <Badge status="warn" text="warning" />
    </Space>
    <h2 class="mt30 mb10">动态</h2>
    <Space :size="20" align="center">
      <Badge :dot="show">
        <span class="u-cube"></span>
      </Badge>
      <Switch v-model:checked="show" />
    </Space>
    <h2 class="mt30 mb10">自定义悬浮状态点的显示文字</h2>
    <Badge :count="5" title="Custom hover text">
      <span class="u-cube"></span>
    </Badge>
    <h2 class="mt30 mb10">多彩徽标</h2>
    <h4 class="mb10">Presets</h4>
    <Space wrap :size="20">
      <Badge
        v-for="color in colors" :key="color"
        :color="color"
        :text="color" />
    </Space>
    <h4 class="mt10 mb10">Custom</h4>
    <Space wrap :size="20">
      <Badge color="#f50" text="#f50" />
      <Badge color="#2db7f5" text="#2db7f5" />
      <Badge color="#87d068" text="#87d068" />
      <Badge color="#108ee9" text="#108ee9" />
    </Space>
  </div>
</template>
<style lang="less" scoped>
.u-cube {
  display: inline-block;
  border-radius: 8px;
  width: 40px;
  height: 40px;
  background: rgba(0, 0, 0, 0.25);
}
.u-svg {
  fill: #f5222d;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/56914.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django实现音乐网站 ⑵

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章1的基础上继续开发&#xff0c;本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表&#xff08;singer&#xff09;结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…

PUBG(最短路BFS)

题目&#xff1a;https://ac.nowcoder.com/acm/contest/62106/E 最近&#xff0c;喜爱ACM的PBY同学沉迷吃鸡&#xff0c;无法自拔&#xff0c;于是又来到了熟悉的ERANGEL。经过一番搜寻&#xff0c;PBY同学准备动身前往安全区&#xff0c;但是&#xff0c;地图中埋伏了许多LYB&…

2023年第四届“华数杯”数学建模思路 - 案例:FPTree-频繁模式树算法

## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c;他与Apriori算法一样也是用来挖掘频繁项集的&#xff0c…

阿里云OSS的开通+配置及其使用

云存储解决方案-阿里云OSS 文章目录 云存储解决方案-阿里云OSS1. 阿里云OSS简介2. OSS开通&#xff08;1&#xff09;打开https://www.aliyun.com/ &#xff0c;申请阿里云账号并完成实名认证。&#xff08;2&#xff09;充值 (可以不用做)&#xff08;3&#xff09;开通OSS&am…

STM32F1基于标准库ST7735 1.8‘‘LCD显示DHT11数据

STM32基于标准库ST7735 1.8‘’LCD显示DHT11数据 &#x1f4cd;HAL库驱动可以参考&#xff1a;《STM32基于HAL工程读取DHT11数据》&#x1f33c;显示效果&#xff1a; &#x1f33b;ST7735 128x160 1.8’LCD屏幕 &#x1f4cc;屏幕资料和相关驱动可以参考《1.8寸TFT LCD128…

《golang设计模式》第一部分·创建型模式-04-抽象工厂模式(Abstract Factory)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 1.1 角色 AbstractFactory&#xff08;抽象工厂&#xff09;&#xff1a;它声明了一组用于创建产品的方法&#xff0c;每一个方法对应一种产品。ConcreteFactory&#xff08;具体工厂&#xf…

ArmSoM-W3之RK3588安装Qt+opencv+采集摄像头画面

1. 简介 场景&#xff1a;在RK3588上做qt开发工作 RK3588安装Qtopencv采集摄像头画面 2. 环境介绍 这里使用了OpenCV所带的库函数捕获摄像头的视频图像。 硬件环境&#xff1a; ArmSoM-RK3588开发板、&#xff08;MIPI-DSI&#xff09;摄像头 软件版本&#xff1a; OS&…

[C++]

C 一.C基础入门1.HelloWorld2.注释3.变量4.常量5.关键字6.命名规则 二.数据类型1.整形2.sizeof关键字3.浮点型4.字符型5.转义字符6.字符串型7.布尔类型8.数据的输入 三.运算符1.算数运算符2.赋值运算符3.比较运算符4.逻辑运算符 一.C基础入门 1.HelloWorld 首先到官网下载并安…

贯穿设计模式--开闭原则

&#x1f335;概述 该原则主要说明的是扩展开放&#xff0c;对修改关闭&#xff0c;即尽量通过扩展软件实体类等来解决需求变化&#xff0c;而不是通过修改已有的代码来完成变化&#xff1b;实现开闭原则的核心思想就是面向抽象编程&#xff0c;强调的是用抽象构建框架&#x…

Windows驱动开发必备工具

Windows驱动开发必备工具 设备树文软件 可以查看设备信息 数字签名工具安装包 开发用的数字签名证书密钥 断点命中工具包&#xff08;双机调试必备&#xff09; 二进制文件解析工具 日志查看工具&#xff08;必备&#xff09; IRP查看工具 C驱动开发相关书籍 有需要工具、书籍…

怎么学习CSS相关技术知识? - 易智编译EaseEditing

学习CSS技术是前端开发中的重要一环&#xff0c;它用于控制网页的样式和布局&#xff0c;使网页更加美观和易于使用。以下是学习CSS技术的几个方面&#xff1a; 基本语法和选择器&#xff1a; 了解CSS的基本语法&#xff0c;学习如何使用选择器来选择HTML元素并应用样式。 样…

vim、awk、tail、grep的使用

vim命令 $定位到光标所在行的行末^定位到光标所在行的行首gg定位到文件的首行G定位到文件的末行dd删除光标所在行ndd删除n行&#xff08;从光标所在行开始&#xff09;D删除光标所在行&#xff0c;使之变为空白行x删除光标所在位置字符nx删除n个字符&#xff0c;从光标开始向后…

使用Flutter的image_picker插件实现设备的相册的访问和拍照

文章目录 需求描述Flutter插件image_picker的介绍使用步骤1、添加依赖2、导入 例子完整的代码效果 总结 需求描述 在应用开发时&#xff0c;我们有很多场景要使用到更换图片的功能&#xff0c;即将原本的图像替换设置成其他的图像&#xff0c;从设备的相册或相机中选择图片或拍…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

visual studio 生成dll文件以及修改输出dll文件名称操作

目录 visual studio 生成dll文件以及修改dll文件名称一、准备测试代码二、设置导出dll属性三、生成dll文件 .lib .dll .pdb 的简单介绍dll文件使用方式lib文件使用方式1、动态链接 &#xff08;原理&#xff09;2、静态链接&#xff1a; visual studio 生成dll文件以及修改dll文…

flex 弹性布局

Flex 布局的使用 任何一个容器都可以指定为 Flex 布局。 .box{ display: flex; //flex作为display的一个属性使用 } 行内元素也可以使用 Flex 布局。 .box{ display: inline-flex; } 注意&#xff1a;设为 Flex 布局以后&#xff0c;子元素的float、clear和vertical-align…

MySQL做分布式锁

分布式锁mysql实现方式 方式1&#xff1a;唯一索引 创建锁表&#xff0c;内部存在字段表示资源名及资源描述&#xff0c;同一资源名使用数据库唯一性限制。多个进程同时往数据库锁表中写入对某个资源的占有记录&#xff0c;当某个进程成功写入时则表示其获取锁成功其他进程由于…

备战秋招 | 笔试强化22

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中&#xff0c;p 指针指向链尾结点的条件是( ) A. p->ne…

小程序云开发快速入门(2/4)

前言 我们对《微信小程序云开发快速入门&#xff08;1/4&#xff09;》的知识进行回顾一下。在上章节我们知道了云开发的优势以及能力&#xff0c;并且我们还完成了码仔备忘录的本地版到网络版的改造&#xff0c;主要学习了云数据库同时还通过在小程序使用云API直接操作了云数…

【无标题】uniapp引入萤石云 真机无法运行 踩坑集合

Uniapp 接入萤石云 踩坑 1.先用了 UIKit Javascript 就是在 pc端 那套流程 npm install ezuikit-jsimport EZUIKit from ezuikit-js;这套流程貌似只适用于pc端&#xff0c;我在接入uniapp的时候没看官网 以为都是一套流程&#xff0c;然后就在uniapp中也来了这一套&#xff0…