打造"皇家"按鈕組件(乾貨滿滿)

前言

Vue的世界中已經充滿了各類各樣的UI庫了,尤爲出名的有ElementUI、Iview、MuseUI等,這幾個也是咱們平常業務開發中常用的UI庫。只使用UI庫的工程師被調侃爲api調用師,這算是一種工程師之間的鄙視了,這種鄙視早晚要還回去的。javascript

最近在家比較閒,嘗試着以成熟UI庫的視角來感覺下其的開發過程,看了這些優秀的代碼,真的以爲本身的代碼有點屎味了!很少說了,讓咱們開始打造本身的UI庫吧,首先看下按鈕是怎麼開發出來的。css

按鈕的使用

在正式開發按鈕以前,咱們先看下按鈕是如何使用的,以及有哪些主要屬性或者功能。這對接下來的api定義是頗有用處的,意義重大。vue

按鈕的主要屬性有這麼幾點:java

  • 是否圓角
  • 是否有邊框
  • 是否可點擊(disabled)
  • 顏色
  • 大小
  • ...

其實還有更多的屬性,這裏咱們不贅述了,知道了某些屬性的開發過程,其餘的也只是照葫蘆畫瓢的;再來看下真實場景中是如何使用的:git

<xch-button color="primary" :disabled="true" :noBorder="true" circle size="m">按鈕</xch-button>
複製代碼

開發前的目錄規劃

清晰的目錄規劃,能爲後面的代碼帶來意想不到的可讀性。一個項目隨着時間的推移,人員的變更,每每會變得愈來愈大,愈來愈難維護。能在前期就規劃好一切固然是最好的,可是又有幾人能作到呢。看下咱們這個按鈕組件的目錄:github

本項目使用的是vue-cli 4.0腳手架生成的,和之前版本生成的目錄大體相同。咱們編寫的代碼基本都在src目錄下,其中components裏放的是咱們的.vue文件,style中放的是樣式文件,本項目咱們採用的是less,和其餘幾個css預處理器都差很少。更具體的代碼邏輯,在下文會依次詳細解說。vue-cli

props 的定義

本文的最低要求是你已經具有了vue的基礎知識。在開發一個組件以前,咱們最好的作法是規劃好這個組件的能力和相關的屬性以及api。特別是api,輕易不要亂改,任何不兼容的修改都是不成熟的標誌,對組件的使用者來講也是不負責任的表現,這也是爲何咱們老是選擇成熟優秀框架的緣由,沒有人但願隔三差五去修改不兼容的代碼。迴歸正題,咱們首先定義下咱們須要的props:api

props: {
    circle: Boolean, // 圓角
    noBorder: Boolean, // 邊框
    disabled: Boolean, // 可點擊
    color: String, // 顏色
    textColor: String, // 文本顏色
    size: {
        type: String,
        validator(value) {
            return ["l", "m", "s", "xs"].indexOf(value) != -1;
        }
    } // 按鈕大小
}
複製代碼

先說一下思想:這些傳入的props,多數是爲了控制某個樣式的class是否須要應用,好比,circle傳入的話,就表明着應用class: btn-circlesize傳入'l'的話,就表明着應用class: btn-l。其餘的屬性也都大體同樣。框架

樣式的計算屬性

上文也講了,props的傳入,其實多數是爲了控制某個樣式是否應用。咱們使用vue的對象語法<div v-bind:class="{ active: isActive }"></div>來定義一個計算屬性buttonCls控制着樣式class這一塊。less

computed: {
    buttonCls() {
        return {
            [`${prefix}`]: true,
            [`${prefix}-circle`]: !!this.circle,
            [`${prefix}-no-border`]: this.noBorder === true,
            [`${prefix}-${this.color}`]: !!this.color,
            [`${prefix}-text-${this.textColor}`]: !!this.textColor,
            [`${prefix}-${this.size}`]: !!this.size
        };
    }
}
複製代碼

整齊劃一的代碼真好看,其中變量是prefix是本身定義的前綴,這樣能很好的區分其餘UI庫,ElementUI是以el-開頭,Iview是以i-開頭。這麼一操做,馬上高大上起來了。不愧是皇家按鈕, 哈哈。

template

template部分相對簡單些,主要是將props和計算屬性應用到button標籤上:

<template>
  <button
    type="button"
    :class="buttonCls"
    :disabled="!!this.disabled"
    @click="click"
  >
    <slot></slot>
  </button>
</template>
複製代碼

重頭戲:樣式

寫到這裏,邏輯部分基本寫完了,一共50行不到的代碼,雖然沒有ElementUI的el-button的功能齊全,但也算是麻雀雖小五臟俱全吧,有興趣的同窗能夠仿照el-button進一步擴展。下面咱們重點學習下怎麼規劃和書寫整潔的less代碼(這部分代碼真的驚豔到我了,我以前一直不重視css的代碼)

在動手寫代碼以前,咱們先梳理下有哪些要點:

  • 全局的樣式抽離成單獨的變量文件,這裏就是var.less,這個習慣必定要養成,在編寫大型的項目或者插件庫的時候,面對堆積成山的代碼量,會複用代碼的人是快樂的,剩下的就是和稀泥的人,天天痛苦不堪。
  • 每一個組件都有本身的less文件,這裏是button.less
  • less語法是很強大的,平時用的最多的就是嵌套語法和變量模式,其實less還有不少的強大的功能,好比函數,混合等,都是很值得咱們去好好理解和學習的

咱們先看下var.less文件,裏面咱們定義了不少變量,好比,顏色、padding等,不只是button組件會用到,之後的其餘組件也會用到,先大概看下:

@prefix: xch-;

// 顏色
@primary-color : #45b984;
@blue-color : #3B91FF; //info
@green-color : #13CE66; //success
@yellow-color : #FFAE00; //warn
@red-color : #E11617; //error
@white-color : #fff;

//Dark, Gray 1-4 more
@dark-color: #333333;
@dark1-color: #555555;
@dark2-color: #666666;
@dark3-color: #777777;
@dark4-color: #999999;

@gray-color: #c1c1c1;
@gray1-color: #d3d3d3;
@gray2-color: #eeeeee;
@gray3-color: #f3f3f3;
@gray4-color: #f5f5f5;

// 按鈕padding
@button-size-normal-padding: 8px 15px;
@button-size-l-padding: 10px 20px;
@button-size-m-padding: 7px 16px;
@button-size-s-padding: 5px 10px;
@button-size-xs-padding: 2px 6px;

// radius
@border-radius : 4px;

//font-size
@font-size : 14px;

// Animation
@animation-time : .3s;
@transition-time : .2s;

@box-shadow-button: 0 1px 1px 0 @gray2-color;

//disabled
@disabled-cursor: not-allowed;
@disabled-color: @dark4-color;
@disabled-border-color: @gray1-color;
@disabled-background-color: @gray4-color;
複製代碼

button.less的代碼,我使用了註釋的方法,儘可能詳細的解說其中的奧妙

@btn-prefix: ~"@{prefix}btn"; // 定義前綴,這是UI組件庫通用的作法

// 定義一個函數,方便控制顏色的切換
// 其中的darken和lighten方法是less自帶的,變淺或者變深,甚是好用
.btn-color(@color, @percent: 10%) {
    background-color: @color;
    border-color: darken(@color, @percent);
    color: @white-color;
    &:hover{
        border-color: lighten(@color, @percent);
        background-color: lighten(@color, @percent);
    }
    &:active {
        border-color: darken(@color, @percent);
        background-color: darken(@color, @percent);
    }
}

.@{btn-prefix} {
    border: none;
    outline: none;
    padding: @button-size-normal-padding;
    display: inline-block;
    border-radius: @border-radius;
    font-size: @font-size;
    ...
    // 顏色切換的精髓
    &.@{btn-prefix} {
        &-primary{
            .btn-color(@primary-color)
        }
        &-red {
            .btn-color(@red-color);
        }
        ...
        
        &-no-border{
            box-shadow: none;
            border-color: transparent !important;
        }
        &-circle {
            border-radius: 20px;
        }
    }
    // 不可點擊時的樣式
    &[disabled] {
        cursor: @disabled-cursor;
        background-color: @disabled-background-color;
        border-color: @disabled-border-color;
        color: @disabled-color;
        &:hover {
            background-color: @disabled-background-color;
            border-color: @disabled-border-color;
            color: @disabled-color;
        }
    }
    // 控制按鈕大小,實際上是控制padding
    &.@{btn-prefix}-l {
        padding: @button-size-l-padding;
    }
    &.@{btn-prefix}-m {
        padding: @button-size-m-padding;
    }
    ...
}
複製代碼

全局註冊和使用

最後就是將本組件註冊到全局,這部分代碼在入口文件main.js中,比較簡單就不累述了;感興趣的同窗能夠思考下怎麼定義另外一個組件button-group來完成按鈕的組合使用。

源碼

還有些細枝末葉的代碼和具體的按鈕效果,這裏也沒有提到,能夠去源碼查看更多詳細的代碼。或者直接下載到本地,跑起來,運行下: git clone https://github.com/xch1029/vue-study.git。附上一句內心話,本身去實現一些UI庫級別的代碼真的能提高不少

相關文章
相關標籤/搜索