基础
1 .用于通知未读数的角标,提醒用户点击
2 .自己有实现基础版本
3 .使用,其实可以看到是直接跟在想要加红点的后面,然后位置是靠传入一个数组来确定的。看了View的这个组件,他其实是用的是传入一个slot。那么整个组件其实有点类似于tooltips,文字提醒那种写法
<div>
<span>花花</span><Badge v-bind:offset="offset" :dot="isDot" />
</div>
4 .之前的源码
<template>
<div class="badge"
:style="computedStyleBadge"
:class="computedBadge">
{{computedValue}}
</div>
</template>
<script>
export default {
props:{
dot:{
type:Boolean,
default:false,
},
// 简单红点
offset:{
type:Array,
default:function(){
return [0,0]
}
},
text:{
type:String,
default:''
},
count:{
type:Number,
default:0
},
overflowCount:{
type:Number,
default:99,
}
},
computed:{
computedBadge(){
if(this.dot){
// 红点的话直接返回这个样式
return 'badge_dot'
}else if(this.text.length>0){
// 汉字的话
return 'badge_text'
}else if(this.count!=0){
// 数字的情况
return 'badge_count'
}
},
computedStyleBadge(){
return {
left:`${this.offset[0]}px`,
top:`${this.offset[1]}px`
}
},
computedValue(){
if(this.text.length>0){
return this.text.slice(0,5)
}else if(this.count!=0){
if(this.overflowCount&&this.count>this.overflowCount){
return this.overflowCount+'+'
}else{
return this.count
}
}
}
}
}
</script>
<style lang="less" src="./index.less"></style>
//想的太简单了
5 .css
@name:.badge;
@{name}{
.r;
display: inline-block;
&_dot{
width: 8px;
height: 8px;
border-radius: 50%;
background: red;
}
&_text{
padding: 3px;
background: red;
font-size: 10px;
color:#fff;
transform: scale(0.8,0.8);
border-radius:5px;
}
&_count{
padding: 3px;
background: red;
font-size: 10px;
color:#fff;
transform: scale(0.8,0.8);
border-radius:5px;
}
}
源码发现
1 .sub 标签定义上标文本。上标文本将会显示在当前文本流中字符高度的一半为基准线的上方,但是与当前文本流中文字的字体和字号都是一样的。上标文本能用来添加脚注,比如 WWW[1]
2 .offset 设置位置用的方法是margin-top,margin-right,并不是实际调整的位置。
3 .这个组件的写法明显和之前的组件不一样。可能换人了,还是他们内部风格没有统一
4 .加入自定义class样式
[${this.className}
]:!!this.className,
5 .样式上下竟然还有重复的地方
6 .状态点那个有点没搞明白存在的意义,所以这里先不研究这个
7 .源码
<template>
<div>
<span v-if="dot" :class="classes" ref="badge">
<slot></slot>
<sup v-show="badge" :class="dotClasses" :style="styles"></sup>
</span>
<span v-else-if="status||color"
:class="classes"
class="li-badge-status"
ref="badge"
>
<span :class="statusClasses" :style="statusStyles"></span>
<span class="li-badge-status-text"><slot name="text">{{text}}</slot></span>
</span>
<span v-else :class="classes" ref="badge">
<slot></slot>
<sup v-if="$slots.count" :style="styles" :class="customCountClasses">
<slot name="count"></slot>
</sup>
<sup v-else-if="hasCount" :style="styles" :class="countClasses" v-show="badge">
<slot name="text">{{finalCount}}</slot>
</sup>
</span>
</div>
</template>
<script>
const pre="li-badge"
export default {
props:{
count:Number,
// 显示的数字,大于overflowCount时,显示${overflowCount}+,为0时隐藏
dot:{
type:Boolean,
default:false
},
// 不显示数字,只显示一个小红点,需要设置count为0
overflowCount:{
type:Number,
default:99,
},
showZero:{
type:Boolean,
default:false,
},
text:{
type:String,
default:''
},
// 自定义文本,如果设置了status,则为状态点的文本
status:{
validator(value){
return ["success","processing","default","error","warning"].includes(value)
}
},
type:{
validator(value){
return ["success","primary","normal","error","warning","info"].includes(value)
}
},
offset:{
type:Array,
},
color:{
type:String,
},
className:String,
},
computed:{
classes(){
return `${pre}`;
},
dotClasses(){
return `${pre}-dot`;
},
statusClasses(){
return []
},
statusStyle(){
return []
},
countClasses(){
return [
`${pre}-count`,
{
[`${this.className}`]:!!this.className,
[`${pre}-count-alone`]:this.alone,
[`${pre}-count-${this.type}`]:!!this.type,
}
]
},
customCountClasses(){
return [
`${pre}-count`,
`${pre}-count-custom`,
{
[`${this.className}`]:!!this.className
}
];
},
statusClasses(){
return []
},
styles(){
const style={}
if(this.offset&&this.offset.length===2){
style['margin-top']=`${this.offset[0]}px`;
style['margin-right']=`${this.offset[1]}px`
}
return style;
},
finalCount(){
if(this.text!=='')return this.text;
return parseInt(this.count)>=parseInt(this.overflowCount)?`${this.overflowCount}+`:this.count
},
badge(){
let status=false
if(this.count){
status=!(parseInt(this.count)===0)
}
if(this.dot){
status=true
if(this.count!==null&&parseInt(this.count)===0){
status=false
}
}
if(this.text!==''){
status=true
}
return status || this.showZero;
},
hasCount(){
if(this.count||this.text!=='')return true;
if(this.showZero&&parseInt(this.count)===0)return true;
else return false;
},
alone(){
return this.$slots.default===undefined;
}
}
}
</script>
<style lang="less" src="./index.less">
</style>
9 .less部分
// @name:.badge;
// @{name}{
// .r;
// display: inline-block;
// &_dot{
// width: 8px;
// height: 8px;
// border-radius: 50%;
// background: red;
// }
// &_text{
// padding: 3px;
// background: red;
// font-size: 10px;
// color:#fff;
// transform: scale(0.8,0.8);
// border-radius:5px;
// }
// &_count{
// padding: 3px;
// background: red;
// font-size: 10px;
// color:#fff;
// transform: scale(0.8,0.8);
// border-radius:5px;
// }
// }
@name:.li-badge;
@{name}{
position: relative;
display: inline-block;
&-dot{
position: absolute;
border-radius: 100%;
background: @error-color;
z-index:10;
top:-4px;
right:-8px;
height: 8px;
width: 8px;
transform: translateX(-50%);
transform-origin:0 center;
box-shadow: 0 0 0 1px #fff;
}
&-count{
font-family: "Monsopaced Number";
vertical-align: middle;
position: absolute;
transform: translateX(50%);
top:-10px;
right: 0;
height: 16px;
border-radius: 10px;
// min-width: 20px;
background: @error-color;
border:1px solid transparent;
color:#fff;
line-height: 16px;
text-align: center;
padding: 0 6px;
font-size: 12px;
white-space: nowrap;
transform-origin: -10% center;
z-index: 10;
box-shadow: 0 0 0 1px #fff;
&-custom{
background: transparent;
color:inherit;
border-color:transparent;
box-shadow: none;
}
&-primary{
background: @primary-color;
}
&-success{
background: @success-color;
}
&-error{
background: @error-color;
}
&-warning{
background: @warning-color;
}
&-info{
background: @info-color;
}
&-normal{
background:@normal-color;
color:@subsidiary-color;
}
}
}