一天一个 Element 组件 - Badge
source link: https://shiningdan.github.io/2020/01/31/%E4%B8%80%E5%A4%A9%E4%B8%80%E4%B8%AA-Element-%E7%BB%84%E4%BB%B6-Badge/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
一天一个 Element 组件 - Badge
本文是 Element 的组件源码学习系列。
项目源码:ElemeFE/element | GitHub,badge:v2.13.0
Badge 组件使用文档:badge 标记
.vue 文件:/packages/badge
.scss 文件:/packages/theme-chalk/badge.scss
.d.ts 文件:/types/badge.d.ts
Props
我们先来看一下 el-badge
这个组件的入参
props: { |
is-dot
is-dot
这个属性比较简单,当这个属性赋值为 true
的时候,右上角的标记是一个小圆点。我们来看一下是如何实现的:
<div class="el-badge"> |
首先,el-badge
的用法,是 <el-badge>
标签,包裹住需要右上角有标签的元素,所以 <template>
中的实现,是返回了一个 <div>
,包裹住被需要有标签的元素 <slot>
,在外面形成一个壳。然后通过 CSS,将标签定位到该元素的右上角。
首先,标签被包裹在一个动效里面,这个动效是 ElementUI 设计的动效,具体的效果可以参考 内置过渡动画。
动效大致的实现思路是,利用 Vue 提供的原生组件 <transition>
,然后实现了具体的类。比如这里的 name = el-zoom-in-center
,就需要实现 el-zoom-in-center-enter
、el-zoom-in-center-active
、el-zoom-in-center-leave
等。具体要实现哪些类,在 Vue 文档中可以找到:过渡 & 动画 | 过渡的类名
在 ElementUI 中,这些类的实现,可以在 transition.scss 这里找到,大家有兴趣可以去看一下 ~
在不考虑动效之后,我们来看一下 is-dot
是如何实现的。
首先,当用户传入 is-dot
的时候,此时 content
为 undefined
computed: { |
所以 <sup>
的 class
为 el-badge__content
和 is-dot
。
然后 :class
的逻辑里面,还有一句是 'is-fixed': $slots.default
。啥意思呢?$slots.default
指的是被 el-badge
包裹住的组件,如果 el-badge
包裹了某个组件,比如一个文本,则 $slots.default
的值就不为空,calss
就还需要加上 is-fixed
。
我们来看一下这几个类的实现逻辑:
// badge.scss |
大体的实现思路如下:
- 使用
<sup>
标签。<sup>
标签在浏览器中,有一个默认的 CSS 属性是vertical-align: super
,该属性的作用是,将<sup>
垂直对齐文本的上标,也就是放在右上角 - 设置
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
的时候,直接将 <sup>
通过 width = height = 8px; border-radius: 50%
,画成一个小圆球就好。
max 和 value
value
有值的时候,content
就有值。此时赋值 v-text="content"
,就是让 <sup>
元素包裹一个文本就好。
我们可以看一下 max
是怎么实现的:
content() { |
如果 max
和 value
都存在并且是数字类型,则比较 value
和 max
的大小,如果 value
小于 max
,则 badge 的内容就是 value
的值。如果 value
大于 max
,则 badge 的内容就是 ${max}+
字符串的值。比如 value = 100; max = 10
,则 badge 的内容就是 10+
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK