Initial commit
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
<template>
|
||||
<!-- 如果不显示badge,则不包裹,直接显示子内容。保证常态下的高性能。但如果设置了alwaysWrapWithContent且有slot内容,则仍然保持包裹层 -->
|
||||
<slot v-if="text == '0' && alwaysWrapWithContent== false"></slot>
|
||||
<!-- 如果有多个子slot,且不设badge,去掉包裹层直接露出slot,会导致flex方向错乱。此时应设置alwaysWrapWithContent为true,总是保留包裹层 -->
|
||||
|
||||
<!-- 微信小程序不支持外部绑定事件 -->
|
||||
|
||||
<template v-else>
|
||||
<view v-if="hasDefaultSlot" style="overflow: visible;" class="badge-wrap" v-bind="$attrs">
|
||||
<!-- 目标内容插槽 -->
|
||||
<slot></slot>
|
||||
|
||||
<!-- badge 文字模式 -->
|
||||
<text v-if="text != '' && text != '0' " :class="['text', 'position', badgeClass]" :style="badgeStyle">
|
||||
{{ text }}
|
||||
</text>
|
||||
|
||||
<!-- badge 红点模式 -->
|
||||
<view v-else-if="text != '0'" :class="['dot', 'position', badgeClass]" :style="badgeStyle"></view>
|
||||
</view>
|
||||
|
||||
<!-- 不包裹,直接显示badge 文字模式 -->
|
||||
<text v-else-if="text != ''" :class="['text', badgeClass]" :style="badgeStyle">
|
||||
{{ text }}
|
||||
</text>
|
||||
|
||||
<!-- 不包裹,直接显示badge 红点模式 -->
|
||||
<view v-else :class="['dot', badgeClass]" :style="badgeStyle"></view>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Badge 数字角标
|
||||
* @description 数字角标(徽章)组件
|
||||
* @uniPlatform {
|
||||
* "app": {
|
||||
* "android": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.21"
|
||||
* },
|
||||
* "ios": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.11"
|
||||
* },
|
||||
* "harmony": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.07"
|
||||
* }
|
||||
* },
|
||||
* "mp": {
|
||||
* "weixin": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.08"
|
||||
* },
|
||||
* "alipay": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.31"
|
||||
* }
|
||||
* },
|
||||
* "web": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
// 禁用自动属性继承,手动控制属性绑定位置
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
externalClasses: ['badge-class']
|
||||
})
|
||||
|
||||
// 定义组件属性接口
|
||||
type Props = {
|
||||
/**
|
||||
* @description badge 的内容。为 "0" 时不显示 badge;为空字符串时显示圆点;有文字则显示文字
|
||||
* @default ""
|
||||
* @uniPlatform {
|
||||
* "app": {
|
||||
* "android": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.21"
|
||||
* },
|
||||
* "ios": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.11"
|
||||
* },
|
||||
* "harmony": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.07"
|
||||
* }
|
||||
* },
|
||||
* "web": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "mp": {
|
||||
* "weixin": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "alipay": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.31"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
text? : string,
|
||||
/**
|
||||
* @description badge 的内联样式,用于覆盖内置 style
|
||||
* @default ""
|
||||
* @uniPlatform {
|
||||
* "app": {
|
||||
* "android": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.21"
|
||||
* },
|
||||
* "ios": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.11"
|
||||
* },
|
||||
* "harmony": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.07"
|
||||
* }
|
||||
* },
|
||||
* "web": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "mp": {
|
||||
* "weixin": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "alipay": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.31"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
badgeStyle? : string,
|
||||
/**
|
||||
* @description badge 的样式类,用于覆盖内置 class
|
||||
* @default ""
|
||||
* @uniPlatform {
|
||||
* "app": {
|
||||
* "android": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.21"
|
||||
* },
|
||||
* "ios": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.11"
|
||||
* },
|
||||
* "harmony": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.07"
|
||||
* }
|
||||
* },
|
||||
* "web": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "mp": {
|
||||
* "weixin": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "alipay": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.31"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
badgeClass? : string.ClassString,
|
||||
/**
|
||||
* @description 当有 slot 内容时,即使 text 为 "0" 也保留包裹层(badge-wrap),避免多个子 slot 时 flex 方向错乱
|
||||
* @default false
|
||||
* @uniPlatform {
|
||||
* "app": {
|
||||
* "android": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.21"
|
||||
* },
|
||||
* "ios": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.11"
|
||||
* },
|
||||
* "harmony": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07",
|
||||
* "unixVaporVer": "5.07"
|
||||
* }
|
||||
* },
|
||||
* "web": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "mp": {
|
||||
* "weixin": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.07"
|
||||
* },
|
||||
* "alipay": {
|
||||
* "uniVer": "x",
|
||||
* "unixVer": "5.31"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
alwaysWrapWithContent? : boolean
|
||||
}
|
||||
|
||||
// 使用 withDefaults 设置默认值
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
text: '',
|
||||
badgeStyle: '',
|
||||
badgeClass: '',
|
||||
alwaysWrapWithContent: false
|
||||
})
|
||||
|
||||
// 1. 获取插槽对象
|
||||
const slots = useSlots();
|
||||
// 2. 定义计算属性来判断默认插槽是否有内容
|
||||
// TODO 这种判断方式的性能有待商榷,这利用了模板的隐式转换
|
||||
const hasDefaultSlot = computed(() => {
|
||||
// console.log('slot: ',slots['default']);
|
||||
return slots['default'] != null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.text {
|
||||
/* background-color: rgba(225, 80, 80, 0.9); */ /* 有透明度*/
|
||||
background-color: rgb(225, 80, 80); /* 无透明度*/
|
||||
min-width: 14px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
border-radius: 7px;
|
||||
/* padding-left: 4px; *//* 保证圆角不裁剪文字 */
|
||||
/* padding-right: 4px; *//* 保证圆角不裁剪文字 */
|
||||
font-size: 10px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dot {
|
||||
background-color: rgb(225, 80, 80);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 有包裹内容,才定位在右上角。所以这个样式是一个单独的class,在slot有内容时才生效 */
|
||||
.position {
|
||||
position: absolute;
|
||||
top: 0px; /* 定位在顶部*/
|
||||
right: 0px; /* 定位在右边*/
|
||||
transform: translate(50%, -50%); /* 中心向右上角偏移,保证中心在元素右上角顶点*/
|
||||
}
|
||||
|
||||
.badge-wrap{
|
||||
/* #ifdef WEB */
|
||||
/* width: fit-content; */
|
||||
/* #endif */
|
||||
align-self: flex-start; /* 默认这样,不然width会变100%。但需要居中时得覆盖重设*/
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user