這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰css
組件 Badge
通常和其它組件配合使用,用於進數字或狀態標記提醒效果。vue
本文將深刻分析組件 Badge
源碼,剖析其實現原理,耐心讀完,相信會對您有所幫助。 組件文檔 Badgenode
packages/badge/src/main.vue
文件是組件源碼實現。 github源碼 main.vuegit
從模板內容看出,組件封裝一個 <div>
元素,包含兩項內容:github
slot
,沒有設置後備內容(默認值);<sup>
元素,用於定義上標文本。<template>
<div class="el-badge"> <slot></slot> <transition name="el-zoom-in-center"> <sup 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 } ]"> </sup> </transition> </div>
</template>
複製代碼
組件渲染後生成一個 class 值爲 el-badge
的 <div>
元素做爲容器。slot
沒有設置後備內容, 只有在組件包裹內容時纔會進行渲染。生成一個 class 值爲 el-badge__content
的<sup>
元素定義上標文本,用於實現數字或狀態標記效果,使用內置組件 transition
實現縮放zoom-in-center
效果。web
<sup>
的可見性由組件 prop hidden
、isDot
和 計算屬性content
進行控制。文本內容爲content
屬性值。根據插槽傳值$slots.default
、type
、isDot
等屬性值動態添加 class,實現不一樣場景的形式展現。gulp
組件提供了5個 prop
。瀏覽器
<script>
export default {
name: 'ElBadge',
props: {
value: [String, Number], // 顯示值
max: Number, // 最大值,超過最大值會顯示 '{max}+'
isDot: Boolean, // 是否顯示小圓點
hidden: Boolean, // 是否隱藏 badge
// 類型
type: {
type: String,
validator(val) {
return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
}
}
},
computed: {
// 計算屬性 上標顯示內容 根據 isDot、value、max進行判斷計算。
content() {
// ...
}
}
};
</script>
複製代碼
各屬性功能描述以下:sass
參數 | 說明 | 類型 | 可選值 | 默認值 |
---|---|---|---|---|
value | 顯示值 | string, number | — | — |
max | 最大值,超過最大值會顯示 '{max}+',要求 value 是 Number 類型 | number | — | — |
is-dot | 小圓點 | boolean | — | false |
hidden | 隱藏 badge | boolean | — | false |
type | 類型 | string | primary / success / warning / danger / info | — |
type
提供了 primary / success / warning / danger / info
可選值,提供了自定義驗證函數。markdown
// 自定義驗證函數
type: {
validator(val) {
// 這個值必須匹配下列字符串中的一個
return ['primary', 'success', 'warning', 'info', 'danger'].indexOf(val) > -1;
}
}
複製代碼
當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制檯的警告。 此時 type
值爲undefined
。
計算屬性content
值是上標顯示內容。 根據 isDot
、value
、max
等prop進行判斷計算。
computed: {
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;
}
}
複製代碼
若使用小圓點形式, isDot
值爲 true
, if (this.isDot) return;
,content
值爲 undefined
。
若不使用小圓點形式時,value
是 Number
類型且設置了 max
,判斷是否超過最大值,超過會顯示 {max}+
,其他狀況 content
值等於 value
值。
<sup>
顯隱邏輯v-show
指令條件 !hidden && (content || content === 0 || isDot)
短路表達式是可知,若 hidden
值爲true
隱藏不顯示,後續條件不執行。
若顯示上標hidden
值爲false
,則繼續根據顯示內容 content
是否存在內容進行判斷, content === 0
邏輯是爲了防止 當 value
爲 0 時,表達式 (content)
返回 false
。 使用圓點形式時,由上文可知content
值 undefined
,isDot
值爲true
,此時表達式返回 true
。
根據 type
會動態的設置 el-badge__content--[type]
,用於不一樣類型的上標顏色顯示 el-badge__content--[primary/success/warning/danger/info]
。當 type
未設置或者不是指定值時,class 值爲el-badge__content--undefined
。
當組件和其它組件配合使用,包裹內容時提供給插槽值 $slots.default
爲 [Vnode]
,設置 is-fixed
固定上標位置-右上角。
若使用小圓點形式時,設置is-dot
控制上標的樣式爲紅點。
組件樣式源碼 packages\theme-chalk\src\badge.scss
使用 scss
的混合指令 b
、 e
、 m
、 when
嵌套生成組件樣式。
// 生成 el-badge
@include b(badge) {
// ...
// 生成 el-badge__content
@include e(content) {
// ...
// 生成 el-badge__content.is-fixed
@include when(fixed) {
// ...
// 生成 el-badge__content.is-fixed.is-dot
@include when(dot) {
// ...
}
}
// 生成 el-badge__content.is-fixed.is-dot
@include when(dot) {
// ...
}
@each $type in (primary, success, warning, info, danger) {
// 生成 .el-badge__content--[primary/success/warning/info/danger]
@include m($type) {
// ...
}
}
}
}
複製代碼
前文可知使用 gulpfile.js
編譯 scss
文件轉換爲CSS
,通過瀏覽器兼容、格式壓縮,最後生成 packages\theme-chalk\lib\badge.scss
,內容格式以下。
.el-badge {
//...
}
.el-badge__content {
//...
}
.el-badge__content.is-fixed {
// ...
}
.el-badge__content.is-fixed.is-dot {
// ...
}
.el-badge__content.is-dot {
// ...
}
.el-badge__content--primary {
background-color: #409eff;
}
.el-badge__content--success {
background-color: #67c23a;
}
.el-badge__content--warning {
background-color: #e6a23c;
}
.el-badge__content--info {
background-color: #909399;
}
.el-badge__content--danger {
background-color: #f56c6c;
}
複製代碼
此文章已收錄到專欄中 👇,能夠直接關注。