Badge 徽章表,红点提醒

基础

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;
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,609评论 0 7
  • 一、样式篇 第1章 初识jQuery (1)环境搭建 进入官方网站获取最新的版本 http://jquery.co...
    凛0_0阅读 3,451评论 0 44
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,162评论 0 21
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,860评论 1 18
  • 1.块级元素和行内元素 块级(block-level)元素;行内(内联、inline-level)元素。 块元素的...
    饥人谷_小侯阅读 2,049评论 1 4