Badge組件

Badge組件主要用於數字或狀態的標記,對於消息類的提醒功能,使用這組件仍是很常見的。具體顯示效果以下圖:css

clipboard.png

無論組件複雜仍是簡單,編碼實現這個組件的都不是源碼分析目的。
源碼分析,在於經過一步步的實現這個功能,在這個過程當中,看本身能學到什麼,發現哪些問題。
而後經過這些問題,去擴展知識點,最終完成 實踐 - 思考 - 擴展 這三步。html

1.實現基本功能,按鈕右上角顯示消息

demo-1連接vue

第一步的實現很簡單,具體的能夠看示例代碼,主要點在於css的思路。api

仔細看,標記相對於父元素,badge的顯示區域定位時只有左上角的一小部分和父元素重疊。經過下面的css能夠實現這個功能。源碼分析

<div class="al-badge">
  <slot></slot>
  <span class="al-badge--content">{{value}}</span>
</div>
.al-badge {
  display: inline-block;
  position: relative;
}
.al-badge--content {
  position: absolute;
  right: 10px;
  top: 0;
  transform: translateX(100%) translateY(-50%);
}

開始的時候,我還想着怎麼經過right + margin屬性實現。可是看源碼發現這種實現方式,感受也是很簡潔。那麼問題就來了,對於css的百分比單位,哪些屬性能夠設置呢?設置後他們的百分比又是相對於哪一個元素?post

發現一篇寫的很好的總結,能夠看一下:詳述css中的百分比值
總結一下:this

  1. widht & heiht屬性,百分比值相對於包含塊的寬高
  2. margin & padding屬性,百分比值相對於包含塊的寬度
  3. font-size屬性,百分比值相對於直接父元素的font-size
  4. line-height屬性,百分比值相對於自身元素的font-size
  5. vertical-align屬性,百分比值相對於自身元素的line-height
  6. top/left/right/bottom屬性,百分比值相對於包含塊寬高
  7. translate中,百分比值相對於自身元素border-box盒模型的寬高

2.實現最大值判斷,超過最大值max時,顯示內容爲max+

demo-2連接編碼

一開始,對於這個需求,個人實現思路是這樣的:spa

<div class="al-badge">
  <slot></slot>
  <span class="al-badge--content" v-if="value <= max">{{value}}</span>
  <span class="al-badge--content" v-if="value > max">{{max+}}</span>
</div>

這算是本身在初期常常容易犯的一個問題吧。濫用v-if v-else
一個好的組件,實現起來,模板一眼看過去,就應該是很簡潔的。過多的v-if只會越讀越糟心,後期維護以及增長新的需求時,也容易各類踩坑。.net

ok,咱們來從新梳理一下上面這段html,兩個v-if的模板,只是針對於不一樣條件下,內容顯示不一樣而已。因此,可不能夠增長一個computed屬性,在js這一層進行簡化?看下面這一段簡化後的:

let ElBadge = {
  name: 'ElBadge',
  //.....
  computed: {
      content: function() {
        if(typeof this.value === 'number' && typeof this.max === 'number') {
          return this.value > this.max ? `${this.max}+` : this.value; 
      }
      return this.value;
    }
  }
};

3.增長展示形式,能夠顯示爲小圓點或單獨使用

demo-3連接

對於這個功能,首先須要解決的是,怎麼判斷組件是單獨使用,仍是包裹了一個子元素

看下Vue關於內容分發的文檔:https://cn.vuejs.org/v2/api/#...

clipboard.png

好,這樣經過$slots.default能夠解決這個問題了,那麼模板上怎麼體現這個區別呢?v-if新增單獨使用的狀況?和上一點相似,咱們須要保證html模板的簡潔,因此經過css類名來作區別,當單獨使用的時候,就不想對於左上角進行定位了。

<div class="al-badge">
  <slot></slot>
  <span v-show="!hidden" 
        class="al-badge--content"
        :class="[
            isDot && 'is-dot', 
            $slots.default && 'is-fixed'
        ]">
       {{content}}
  </span>
</div>
.al-badge--content {
  //.....
  &.is-fixed {
    position: absolute;
    right: 10px;
    top: 0;
    transform: translateX(100%) translateY(-50%);
  }

  &.is-dot {
    right: 5px;
    width: 8px;
    height: 8px;
    padding: 0;
  }
}

總結

經過Badge組件

  • 學到了模板代碼的正確組織方式,如何經過computed,css類名等來簡化模板的編寫,使其更加清晰可讀。
  • 以及$slots.default API的使用
  • 擴展了對於css百分比值的認識。

參考文獻:

  1. 詳述css中的百分比值
相關文章
相關標籤/搜索