爲鍛鍊封裝組件得能力,我打算研究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組件裏寫下以下代碼: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;
}
複製代碼
便可爲挨着的按鈕們增長一個間距,效果如圖:
這三個同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組件:
<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>
複製代碼
這樣就達到了效果:
效果以下:
如今咱們的組件已經支持這兩種樣式的按鈕了。
新增一個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>
複製代碼
呈現效果以下:
<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…