Element組件研究-Button

前言

爲鍛鍊封裝組件得能力,我打算研究Elment UI組件,學習人家的設計和代碼。vue

第一個想研究的就是Button組件,是咱們最經常使用也最熟悉的,對標官方文檔中介紹的Button特性,咱們一個個來實現它們。git

準備工做

使用vue-cli新建一個空項目web

vue create my-element-ui
複製代碼

在項目中的components文件夾下新建Button文件夾,再新建一個index.vue,寫按鈕組件的代碼。在根目錄下新建views文件夾,再新建ButtonShownPage文件夾,再新建index.vue,在此頁面展現按鈕組件。vue-cli

在ButtonShownPage中我寫下element-ui

<template>
    <el-button @click="handleClick">默認按鈕</el-button>
</template>

<script>
import ElButton from '../../components/Button/index'

export default {
    name: 'ButtonShownPage',
    methods: {
        handleClick(evt) {
            console.log('handleClick', evt);
        }
    },
    components: {
        ElButton
    }
}
</script>
複製代碼

這樣咱們開始專心寫Button的代碼,使其有正確的呈現瀏覽器

編寫基本的Button

通過簡單的摸索,我在Button組件裏寫下以下代碼:bash

<template>
    <button 
        class="el-button"
        @click="handleClick"
    >
        <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>

<script>

export default {
    name: 'Button',
    methods: {
        handleClick(evt) {
            this.$emit('click', evt);
        }
    }
}
</script>

<style>
.el-button {
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    background: #fff;
    border: 1px solid #dcdfe6;
    color: #606266;
    -webkit-appearance: none;
    text-align: center;
    box-sizing: border-box;
    outline: none;
    margin: 0;
    transition: .1s;
    font-weight: 500;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    padding: 12px 20px;
    font-size: 14px;
    border-radius: 4px;
}

.el-button:focus, .el-button:hover {
    color: #409eff;
    border-color: #c6e2ff;
    background-color: #ecf5ff;
}

.el-button:active {
    color:#3a8ee6;
    border-color:#3a8ee6;
    outline:none
}
</style>
複製代碼

使用button標籤做爲組件的基礎,編寫包含默認、focus、hover、active幾種狀態下的樣式。利用slot包含按鈕內容,click事件暴露出去。最基本的按鈕就有了。app

增長類型

如今讓咱們的button支持type,分別是primary,success,info,warning,danger。工具

先在ButtonShownPage中寫測試代碼:學習

<el-button @click="handleClick">默認按鈕</el-button>
<el-button type="primary">主要按鈕</el-button>
<el-button type="success">成功按鈕</el-button>
<el-button type="info">信息按鈕</el-button>
<el-button type="warning">警告按鈕</el-button>
<el-button type="danger">危險按鈕</el-button>
複製代碼

再在Button中寫邏輯代碼:

<template>
    <button 
        class="el-button"
        :class="[type ? 'el-button--' + type : '']"
        @click="handleClick"
    >
        <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>

<script>

export default {
    name: 'Button',
    props: {
        type: {
            type: String,
            default: 'default',
        },
    },
    methods: {
        handleClick(evt) {
            this.$emit('click', evt);
        }
    }
}
</script>
複製代碼

加一個prop名爲type,默認爲default,根據傳入的值,爲button標籤添加樣式。如傳入的是primary,那麼button就有了.el-button--primary這個class,咱們再添加樣式:

.el-button--primary {
    color: #fff;
    background-color: #409eff;
    border-color: #409eff;
}

.el-button--primary:focus, .el-button--primary:hover {
    background: #66b1ff;
    border-color: #66b1ff;
    color: #fff;
}
複製代碼

功能完成,另外添加個這樣的樣式:

.el-button+.el-button {
    margin-left: 10px;
}
複製代碼

便可爲挨着的按鈕們增長一個間距,效果如圖:

plain、round和circle

這三個同type一模一樣,都是經過添加class來控制樣式

<template>
    <button 
        class="el-button"
        :class="[type ? 'el-button--' + type : '', { 'is-plain': plain, 'is-round': round, 'is-circle': circle }]"
        @click="handleClick"
    >
        <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>
複製代碼

這時在props裏增長plain, round, circle屬性。

props: {
        type: {
            type: String,
            default: 'default',
        },
        plain: Boolean,
        round: Boolean,
        circle: Boolean
    },
複製代碼

因爲要引用樣式太多了,原理又相同,我經過瀏覽器開發者工具直接將elementui的樣式直接整個copy過來放在assets文件夾中。

這樣,效果以下:

咱們的按鈕支持多種形態了。

這裏咱們將全部的elemnnt的樣式都拷貝過來了,因此後續就不須要關心樣式的編寫,只關心標籤和js的邏輯,便可實現相應功能,但能夠在呈現結果中,利用瀏覽器工具繼續研究樣式的細節。

支持icon

新增一個Icon組件:

<template>
  <i :class="'el-icon-' + name"></i>
</template>

<script>
  export default {
    name: 'ElIcon',
    props: {
      name: String
    }
  };
</script>
複製代碼

將Icon組件引入Button內,

<template>
    <button 
        class="el-button"
        :class="[type ? 'el-button--' + type : '', { 'is-plain': plain, 'is-round': round, 'is-circle': circle }]"
        @click="handleClick"
    >
        <el-i :class="icon" v-if="icon"></el-i>
        <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>
複製代碼

這樣就達到了效果:

禁用狀態

  1. 給組件增長一個屬性disabled
  2. 給button標籤的屬性disabled綁定組件disabled屬性,確保點擊事件不生效
  3. 在:class中加一條'is-disabled': disabled便可。

效果以下:

文字按鈕,圖標按鈕

如今咱們的組件已經支持這兩種樣式的按鈕了。

按鈕組

新增一個ButtonGroup組件,關鍵點仍是在於控制樣式

<template>
  <div class="el-button-group">
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'ElButtonGroup'
  };
</script>
複製代碼

使用以下:

<el-button-group>
    <el-button type="primary" icon="el-icon-arrow-left">上一頁</el-button>
    <el-button type="primary">下一頁<i class="el-icon-arrow-right el-icon--right"></i></el-button>
</el-button-group>
複製代碼

呈現效果以下:

加載中

  1. 給組件增長一個屬性loading
  2. 給class增長一條'is-loading': loading, 把disabled變成:disabled="disabled || loading"
  3. 把 <el-i :class="icon" v-if="icon>變成
<el-i class="el-icon-loading" v-if="loading"></el-i>
<el-i :class="icon" v-if="icon && !loading"></el-i>
複製代碼

效果以下:

按鈕大小

同type一個套路,加一個size屬性,控制class。

總結

基本的按鈕組件就研究到這。所有示例以下:

本文的全部代碼已上傳至碼雲:gitee.com/DaBuChen/my…

相關文章
相關標籤/搜索