为锻炼封装组件得能力,我打算研究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…