vue实现消息badge标记_⼀天⼀个Element组件-Badge 本⽂是 Element 的组件源码学习系列。
Badge 组件使⽤⽂档:badge 标记
Props
我们先来看⼀下 el-badge 这个组件的⼊参
props: {
value: [String, Number],
max: Number,
isDot: Boolean,
hidden: Boolean,
type: {
type: String,
validator(val) {
return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
}
}
},
is-dot
is-dot 这个属性⽐较简单,当这个属性赋值为 true 的时候,右上⾓的标记是⼀个⼩圆点。我们来看⼀下是如何实现的:
v-show="!hidden && (content || content === 0 || isDot)"
v-text="content"
class="el-badge__content"
:class="[
'el-badge__content--' + type,
{
'is-fixed': $slots.default,
'is-dot': isDot
}
]">
⾸先,el-badge 的⽤法,是 标签,包裹住需要右上⾓有标签的元素,所以 中的实现,是返回了⼀个
,包裹住被需要有标签的元素 ,在外⾯形成⼀个壳。然后通过 CSS,将标签定位到该元素的右上⾓。
动效
⾸先,标签被包裹在⼀个动效⾥⾯,这个动效是 ElementUI 设计的动效,具体的效果可以参考 内置过渡动画。
动效⼤致的实现思路是,利⽤ Vue 提供的原⽣组件 ,然后实现了具体的类。⽐如这⾥的 name = el-zoom-in-center,就需要实现 el-zoom-in-center-enter、el-zoom-in-center-active、el-zoom-in-center-leave 等。具体要实现哪些类,在 Vue ⽂档中可以到:过渡& 动画 | 过渡的类名
在 ElementUI 中,这些类的实现,可以在 transition.scss 这⾥到,⼤家有兴趣可以去看⼀下 ~
CSS
在不考虑动效之后,我们来看⼀下 is-dot 是如何实现的。
⾸先,当⽤户传⼊ is-dot 的时候,此时 content 为 undefined
computed: {
content() {
if (this.isDot) return;
}
}
所以 的 class 为 el-badge__content 和 is-dot。
然后 :class 的逻辑⾥⾯,还有⼀句是 'is-fixed': $slots.default。啥意思呢?$slots.default 指的是被 el-badge 包裹住的组件,如果 el-badge 包裹了某个组件,⽐如⼀个⽂本,则 $slots.default 的值就不为空,calss 就还需要加上 is-fixed。
我们来看⼀下这⼏个类的实现逻辑:
// badge.scss
@include b(badge) {
position: relative;
vertical-align: middle;
display: inline-block;
@include e(content) {
background-color: $--badge-background-color;
border-radius: $--badge-radius;
color: $--color-white;
display: inline-block;
font-size: $--badge-font-size;
height: $--badge-size;
line-height: $--badge-size;
padding: 0 $--badge-padding;
text-align: center;
white-space: nowrap;
border: 1px solid $--color-white;
@include when(fixed) {
position标签属性
position: absolute;
top: 0;
right: #{1 + $--badge-size / 2};
transform: translateY(-50%) translateX(100%);
@include when(dot) {
right: 5px;
}
}
@include when(dot) {
height: 8px;
width: 8px;
padding: 0;
right: 0;
border-radius: 50%;
}
}
⼤体的实现思路如下:使⽤ 标签。 标签在浏览器中,有⼀个默认的 CSS 属性是 vertical-align: super,该属性的作⽤是,将 垂直对齐⽂本的上标,也就是放在右上⾓
设置 position: relative 包裹住需要有⾓标的 HTML 元素,⽅便把⾓标通过 position: absolute 定位到右上⾓;设置 display: inline-block,让被包裹元素和⾓标在⼀⾏
如果被包裹元素存在,则触发 @include when(fixed) 函数,设置 position: absolute; top: 0; right: #{1 + $--badge-size / 2};,将⾓标调整到右上⾓向左 10px。
针对元素的宽度和⾼度,做⼀些调整:transform: translateY(-50%) translateX(100%);。这句话⼤概的
意思是:把元素沿着横向(x轴)移动⾃⾝宽度的100%,⼀般是从左侧为开始点也就是0点。⽽数值是100%,所以是从右侧0点向左移动⾃⾝宽度的100%。同时,向上移动⾃⾝⾼度的 50%
所以,整体实现的效果是,如果设置 right: 0px; transform: translateY(-50%) translateX(100%);。则 badge 放在被定位元素的右上⾓,从 X 轴上⾯没有重合,Y 轴上⾯,badge 上移了 50% 的⾼度。然后为了美观,将 right 设置为 #{1 + $--badge-size / 2};。通过var.scss ⽂件,我们可以得到 $--badge-size 默认是 18px。所以默认情况下,badge 在被包裹元素的右上⾓,朝左移动 10px,⾼度有50% 的重合。
当然,如果有 is-Dot 的时候,直接将 通过 width = height = 8px; border-radius: 50%,画成⼀个⼩圆球就好。
max 和 value
value 有值的时候,content 就有值。此时赋值 v-text="content",就是让 元素包裹⼀个⽂本就好。
我们可以看⼀下 max 是怎么实现的:
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;
}
如果 max 和 value 都存在并且是数字类型,则⽐较 value 和 max 的⼤⼩,如果 value ⼩于 max,则 badge 的内容就是 value 的值。如果 value ⼤于 max,则 badge 的内容就是 ${max}+ 字符串的值。⽐如 value = 100; max = 10,则 badge 的内容就是 10+
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论