前端学习案例-手动封装element-ui里面的button组件
首先我们知道vue里面包含有父子组件
但是你知道如果要进行一个element的手动组件封装
怎么封装吗
1首先第一步
首先我们建立一个组件
最好设置在一个文件目录下比如components
只是一个普通的组件
叫做OneButton.vue
<template>
<button class="one-button">
按钮组件
</button>
</template>
<script>
export default {
name: 'oneButton'
}
</script>
<style lang="scss">
</style>
要想使用该组件
就需要进行全局注册
就是在main.js里面注册了
import Vue from 'vue'
import App from './App.vue'
// 第一步:导入button组件
import OneButton from './components/button.vue'
Vue.config.productionTip = false
// 第二步:注册组件,设置(组件名,组件)
Vue.component(OneButton.name, OneButton)
new Vue({
render: h => h(App)
}).$mount('#app')
注册完成以后就可以进行使用了
<template>
<div id="app">
<one-button>按钮</one-button>
</div>
</template>
<script>
export default {
name: 'App',
components: {}
}
</script>
<style lang="scss">
</style>
到这里
我们可以看到 就会显示一个普通按钮了
但是吧 这样的封装过于简单
能不能实现更加复杂的操作呢
于是
我们需要封装一个有element-ui风格的组件
好 那我们继续实现
我们先让文字可以自由的输入
那就要利用插槽了
<template>
<button class="one-button">
<span><slot></slot></span>
</button>
</template>
我们的文件需要做以上处理
<template>
<div>
<one-button>歌谣</one-button>
<one-button>帅气</one-button>
<one-button>关注我</one-button>
</div>
</template>
加上基本样式
<style lang="scss">
.one-button{
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #ffffff;
border: 1px solid #dcdfe6;
color: #606266;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: 0.1s;
font-weight: 500;
//禁止元素的文字被选中
-moz-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
&:hover,
&:hover{
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
}
</style>
这样文字的效果就实现了
到了这里 你又想element里面可以控制type属性控制按钮样式
怎么可以实现呢
父元素传递type值
<template>
<div id="app">
<div class="row">
<one-button>按钮</one-button>
<one-button type="primary">primary按钮</one-button>
<one-button type="success">success按钮</one-button>
<one-button type="info">info按钮</one-button>
<one-button type="danger">danger按钮</one-button>
<one-button type="warning">warning按钮</one-button>
</div>
</div>
</template>
子元素接收当然props了
export default {
name: 'oneButton',
// 此时对props进行校验,值接收string类型的type值
props: {
type:{
type: String,
// 设置默认值:如果不传值,那么使用default
default: 'default'
}
},
created () {
console.log(this.type)//defalut primary success info danger warning
}
}
做过处理以后根据type就可以实现数据的操作了
动态绑定样式
<template>
<button class="one-button" :class="`one-button-${type}`">
<span><slot></slot></span>
</button>
</template>
最后定义好样式
.one-button-primary{
color:#fff;
background-color: #409eff;
border-color: #409eff;
&:hover,
&:focus{
background: #66b1ff;
background-color: #66b1ff;
color: #fff;
}
}
.one-button-success{
color:#fff;
background-color: #67c23a;
border-color: #67c23a;
&:hover,
&:focus{
background: #85ce61;
background-color: #85ce61;
color: #fff;
}
}
.one-button-info{
color:#fff;
background-color: #909399;
border-color: #909399;
&:hover,
&:focus{
background: #a6a9ad;
background-color: #a6a9ad;
color: #fff;
}
}
.one-button-warning{
color:#fff;
background-color: #e6a23c;
border-color: #e6a23c;
&:hover,
&:focus{
background: #ebb563;
background-color: #ebb563;
color: #fff;
}
}
.one-button-danger{
color:#fff;
background-color: #f56c6c;
border-color: #f56c6c;
&:hover,
&:focus{
background: #f78989;
background-color: #f78989;
color: #fff;
}
}
运行
nice呀 有没有
这个时候你可能会想
如果设置plain属性怎么设置呢
和type类型相同,我们只要将样式先设置好,然后通过父组件传递过来的值进行判断,就可以设置plain属性了。
和type类型相同,我们只要将样式先设置好,然后通过父组件传递过来的值进行判断,就可以设置plain属性了。
第一步:父组件组件传递plain值
<template>
<div id="app">
<div class="row">
<one-button plain>按钮</one-button>
<one-button plain type="primary">primary按钮</one-button>
<one-button plain type="success">success按钮</one-button>
<one-button plain type="info">info按钮</one-button>
<one-button plain type="danger">danger按钮</one-button>
<one-button plain type="warning">warning按钮</one-button>
</div>
</div>
</template>
第二步:子组件接收负组件传递的数据,同样进行props校验,并且设置默认值为false
props: {
plain: {
type: Boolean,
default: false
}
}
第三步:通过绑定类名的方法动态控制样式,由于plain类型是布尔值,所以在类型中我们使用对象的形式来控制样式
<template>
<button class="one-button" :class="[`one-button-${type}`,{
'is-plain':plain
}]">
<span><slot></slot></span>
</button>
</template>
第四步:设置不同类型的样式,由于plain类型是以对象的形式在类中定义的,所以使用获取属性的方法定义样式
// 朴素按钮样式
.one-button.is-plain{
&:hover,
&:focus{
background: #fff;
border-color: #489eff;
color: #409eff;
}
}
.one-button-primary.is-plain{
color: #409eff;
background: #ecf5ff;
&:hover,
&:focus{
background: #409eff;
border-color: #409eff;
color: #fff;
}
}
.one-button-success.is-plain{
color: #67c23a;
background: #c2e7b0;
&:hover,
&:focus{
background: #67c23a;
border-color: #67c23a;
color: #fff;
}
}
.one-button-info.is-plain{
color: #909399;
background: #d3d4d6;
&:hover,
&:focus{
background: #909399;
border-color: #909399;
color: #fff;
}
}
.one-button-warning.is-plain{
color: #e6a23c;
background: #f5dab1;
&:hover,
&:focus{
background: #e6a23c;
border-color: #e6a23c;
color: #fff;
}
}
.one-button-danger.is-plain{
color: #f56c6c;
background: #fbc4c4;
&:hover,
&:focus{
background: #f56c6c;
border-color: #f56c6c;
color: #fff;
}
}
nice呀 有没有
round属性也是一样
button组件的round属性
设置round属性和之前的相似,只要在组件中定义好了样式,动态获取属性值即可。
获取属性值:
round: {
type: Boolean,
default: false
}
round样式:
.one-button.is-round{
border-radius: 20px;
padding: 12px 23px;
}
看看效果
nice有没有
到这里
我们看看字体图标怎么实现
字体图标也是要引入的
第一步:在main.js中引入字体图标
import './assets/fonts/iconfont.css'
第二步:将下载的字体图标css文件中的类名做修改,我将icon全部改为了one-icon,并且将初始的iconfont类改为了[class*='one-icon'],当类名中有one-icon时使用,如下
[class*='one-icon'] {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.one-icon-bluetoothoff:before {
content: "\e697";
}
第三步:父组件传递图标名,子组件接收并且放到图标中
父组件传值:
<div class="row">
<one-button icon="bluetoothon"></one-button>
<one-button type="primary" icon="camera">照相机</one-button>
<one-button type="success" icon="course"></one-button>
<one-button type="info" icon="bluetooth_link"></one-button>
<one-button type="danger" icon="addto"></one-button>
<one-button type="warning" icon="audio"></one-button>
</div>
子组件接收:
icon: {
type: String,
default: ''
}
使用接收到的字体图标。在没有传入icon时隐藏<i>标签,在slot插槽没有传入值时,不显示<span>标签
<template>
<button class="one-button" :class="[`one-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
}]">
<i v-if="icon" :class="`one-icon-${icon}`"></i>
<!-- 如果没传入文本插槽,则不显示span内容 -->
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
第四步:设置icon配套样式,使图标和文字之间有一定间隔
.one-button [class*=one-icon-]+span{
margin-left: 5px;
}
查看效果
nice有没有
到这里
我们想一想element里面还有点击事件怎么实现
button组件中的点击事件
我们在使用组件时,直接给组件定义事件是不会被触发的。我们需要在组件中定义一个点击事件,这个点击事件不进行其他操作,只出发父组件中的点击事件。
组件中的定义点击事件:
<template>
<button class="one-button" :class="[`one-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
}]"
@click="handleClick"
>
<i v-if="icon" :class="`one-icon-${icon}`"></i>
<!-- 如果没传入文本插槽,则不显示span内容 -->
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
定义一个点击事件,这个点击事件的作用是调用父组件中的点击事件,并且回调
methods: {
handleClick (e) {
this.$emit('click', e)
}
}
父组件在使用时定义自己的点击事件,其本质是子组件中的点击事件触发父组件中的点击事件。
<div class="row">
<one-button @click="getInfo">按钮</one-button>
</div>
methods: {
getInfo () {
console.log('获取信息!!')//获取信息!!
}
}
就很nice
按钮中会设置是否禁用
我们可以通过父子传值
给子组件设置样式实现
button组件中的disabled属性
和之前相似,只要父子组件传值并且动态获取这个值并且赋给disabled属性,并且设置一个disabled样式即可。
<div class="row">
<one-button @click="getInfo" disabled>按钮</one-button>
</div>
<template>
<button class="one-button" :class="[`one-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
'is-disabled':disabled
}]"
@click="handleClick"
:disabled="disabled"
>
<i v-if="icon" :class="`one-icon-${icon}`"></i>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
disabled: {
type: Boolean,
default: false
}
disabled样式:
.one-button.is-disabled{
cursor: no-drop;
}
至此 element中的button组件就封装完成了 是不是很nice
下次有时间继续封转其他的
看看封装的总代码
<template>
<button class="one-button" :class="[`one-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
'is-disabled':disabled
}]"
@click="handleClick"
:disabled="disabled"
>
<i v-if="icon" :class="`one-icon-${icon}`"></i>
<!-- 如果没传入文本插槽,则不显示span内容 -->
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
<script>
export default {
name: 'oneButton',
// 此时对props进行校验,值接收string类型的type值
props: {
type: {
type: String,
// 设置默认值:如果不传值,那么使用default
default: 'defalut'
},
plain: {
type: Boolean,
default: false
},
round: {
type: Boolean,
default: false
},
circle: {
type: Boolean,
default: false
},
icon: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
created () {
// 显示所有插槽
// console.log(this.$slots)
},
methods: {
// 定义一个点击事件,这个点击事件的作用是调用父组件中的点击事件,并且回调
handleClick (e) {
this.$emit('click', e)
}
}
}
</script>
<style lang="scss" scoped>
.one-button{
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #ffffff;
border: 1px solid #dcdfe6;
color: #606266;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: 0.1s;
font-weight: 500;
//禁止元素的文字被选中
-moz-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
&:hover,
&:focus{
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
}
.one-button-primary{
color:#fff;
background-color: #409eff;
border-color: #409eff;
&:hover,
&:focus{
background: #66b1ff;
background-color: #66b1ff;
color: #fff;
}
}
.one-button-success{
color:#fff;
background-color: #67c23a;
border-color: #67c23a;
&:hover,
&:focus{
background: #85ce61;
background-color: #85ce61;
color: #fff;
}
}
.one-button-info{
color:#fff;
background-color: #909399;
border-color: #909399;
&:hover,
&:focus{
background: #a6a9ad;
background-color: #a6a9ad;
color: #fff;
}
}
.one-button-warning{
color:#fff;
background-color: #e6a23c;
border-color: #e6a23c;
&:hover,
&:focus{
background: #ebb563;
background-color: #ebb563;
color: #fff;
}
}
.one-button-danger{
color:#fff;
background-color: #f56c6c;
border-color: #f56c6c;
&:hover,
&:focus{
background: #f78989;
background-color: #f78989;
color: #fff;
}
}
// 朴素按钮样式
.one-button.is-plain{
&:hover,
&:focus{
background: #fff;
border-color: #489eff;
color: #409eff;
}
}
.one-button-primary.is-plain{
color: #409eff;
background: #ecf5ff;
&:hover,
&:focus{
background: #409eff;
border-color: #409eff;
color: #fff;
}
}
.one-button-success.is-plain{
color: #67c23a;
background: #c2e7b0;
&:hover,
&:focus{
background: #67c23a;
border-color: #67c23a;
color: #fff;
}
}
.one-button-info.is-plain{
color: #909399;
background: #d3d4d6;
&:hover,
&:focus{
background: #909399;
border-color: #909399;
color: #fff;
}
}
.one-button-warning.is-plain{
color: #e6a23c;
background: #f5dab1;
&:hover,
&:focus{
background: #e6a23c;
border-color: #e6a23c;
color: #fff;
}
}
.one-button-danger.is-plain{
color: #f56c6c;
background: #fbc4c4;
&:hover,
&:focus{
background: #f56c6c;
border-color: #f56c6c;
color: #fff;
}
}
// round属性
.one-button.is-round{
border-radius: 20px;
padding: 12px 23px;
}
// circle属性
.one-button.is-circle{
border-radius: 50%;
padding: 12px;
}
// icon配套样式
.one-button [class*=one-icon-]+span{
margin-left: 5px;
}
// disabled属性
.one-button.is-disabled{
cursor: no-drop;
}
</style>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!