基于element-ui的vue组件的封装(一)
基于element-ui的vue组件的封装
实例内容
封装常见的功能组件 (Button、Modal、Form相关),封装完成后封装成UI组件库发布到NPM上
涉及知识点
-
vue基础语法
-
组件基本语法
-
子健通讯(sync、provide、inject)
-
插槽使用
-
prop校验
-
过渡与动画处理
-
计算属性和监听属性
-
v-model语法糖
-
vue插件机制
-
npm发布
实例目的
-
掌握组件封装的语法和技巧
-
学会造轮子,了解组件库实现原理
-
搭建和积累自己的组件库
一、使用vue脚手架初始化一个项目
使用 vue created itcast-ui,创建一个名为itcast-ui的项目
二、如何封装,注册和使用一个组件
在component下创建一个button.vue的文件,放置button组件代码。创建一个组件的button组件,并指定name为DLButton。
<template>
<button class="dl-button">
按钮组件
</button>
</template>
<script>
export default {
name: 'DlButton'
}
</script>
<style lang="scss">
</style>
创建组件完成后,不能再项目中直接使用,需要到main.js中注册才可以使用
import Vue from 'vue'
import App from './App.vue'
//第一步:导入button组件
import DlButton from './components/button.vue'
Vue.config.productionTip = false
//第二步: 注册组件, 设置(组件名, 组件)
Vue.component(DlButton.name, DlButton)
new Vue({
render: h => h(App)
}).$mount('#app')
注册完成后,组件就可以在项目中直接使用了
<template>
<div>
<dl-button></dl-button>
</div>
</template>
按钮效果: ![]()
组件最简单的封装,注册和使用的方法就是这个流程
三、封装一个element-ui风格的按钮
需要使用的知识:
-
组件通讯
-
组件插槽
-
props校验
参数支持:
| 参数名 | 参数描述 | 参数类型 | 默认值 |
|---|---|---|---|
| type | 按钮类型(primary/success/warning/danger/info) | string | default |
| plain | 是否是朴素按钮 | boolean | false |
| round | 是否是圆角按钮 | boolean | false |
| circle | 是否是原型按钮 | boolean | false |
| disabled | 是否禁用按钮 | boolean | false |
| icon | 图标类名 | string | 无 |
事件支持:
| 事件名 | 事件描述 |
|---|---|
| click | 点击事件 |
使用插槽:
简单来说,凡是希望组件中内容可以灵活设置的地方,都需要用到slot插槽来自定义内容
使用slot来定义按钮的文本内容:
<template>
<button class="dl-button">
<span><slot></slot></span>
</button>
</template>
在使用时就可以直接输入文本,定义按钮文本内容了:
<template>
<div>
<dl-button>登录</dl-button>
<dl-button>删除</dl-button>
<dl-button>取消</dl-button>
</div>
</template>
效果:![]()
button组件基础样式:
.dl-button {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
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
}
}
效果:
3.1button组件的type属性
让按钮支持type属性,使得按钮支持不同样式:
第一步:父组件传递type属性
<template>
<div id="app">
<div class="row">
<dl-button>按钮</dl-button>
<dl-button type="primary">按钮</dl-button>
<dl-button type="success">按钮</dl-button>
<dl-button type="danger">按钮</dl-button>
<dl-button type="warning">按钮</dl-button>
<dl-button type="info">按钮</dl-button>
</div>
</template>
第二步:子组件接受父组件传递的数据
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进行校验,如果传递了非String类型的值(这里我传递了111),将会报错
failed for prop "type". Expected String with value "111", got Number with value 111.
第三步:通过绑定类名的方法动态控制样式
<template>
<button class="dl-button" :class="`dl-button-${type}`">
<span><solt></solt></span>
</button>
</template>
第四部:设置不同的样式
.dl-button-primary {
color: #fff;
background-color: #409eff;
border-color: #409eff;
&:hover,
&:focus {
background: #66b1ff;
background-color: #66b1ff;
color: #fff;
}
}
.dl-button-success {
color: #fff;
background-color: #67c23a;
border-color: #67c23a;
&:hover,
&:focus {
background: #85ce61;
background-color: #85ce61;
color: #fff;
}
}
.dl-button-info {
color: #fff;
background-color: #909399;
border-color: #909399;
&:hover,
&:focus {
background: #a6a9ad;
background-color: #a6a9ad;
color: #fff;
}
}
.dl-button-warning {
color: #fff;
background-color: #e6a23c;
border-color: #e6a23c;
&:hover,
&:focus {
background: #ebb563;
background-color: #ebb563;
color: #fff;
}
}
.dl-button-danger {
color: #fff;
background-color: #f56c6c;
border-color: #f56c6c;
&:hover,
&:focus {
background: #f78989;
background-color: #f78989;
color: #fff;
}
}
第五步:至此就完成了按钮样式的设置,查看效果

3.2button组件的plain属性
和type类型相同,我们只要将样式先设置好,然后通过父组件传递过来的值进行判断,就可以设置plain属性了
第一步:父组件传递plain值
<template>
<div id="app">
<div class="row">
<dl-button plain>按钮</dl-button>
<dl-button plain type="primary">primary按钮</dl-button>
<dl-button plain type="success">success按钮</dl-button>
<dl-button plain type="info">info按钮</dl-button>
<dl-button plain type="danger">danger按钮</dl-button>
<dl-button plain type="warning">warning按钮</dl-button>
</div>
</div>
</template>
第二步:子组件接收父组件传递的数据,同样进行props校验,并且设置默认值为false
props: {
plain: {
type: Boolean,
default: false
}
}
第三步通过绑定类名的方式动态控制样式,由于plain类型是布尔值,所以在类型中,我们使用对象的形式来控制样式
<template>
<button class="dl-button" :class="[`dl-button-${type}`,{
'is-plain':plain
}]">
<span><slot></slot></span>
</button>
</template>
第四部:设置不同类型的样式,由于plain类型是以对象的形式在类中定义的,所以使用获取属性的方法定义样式
// 朴素按钮样式
.dl-button.is-plain {
&:hover,
&:focus {
background: #fff;
border-color: #489eff;
color: #409eff;
}
}
.dl-button-primary.is-plain {
color: #409eff;
background: #ecf5ff;
&:hover,
&:focus {
background: #409eff;
border-color: #409eff;
color: #fff;
}
}
.dl-button-success.is-plain {
color: #67c23a;
background: #c2e7b0;
&:hover,
&:focus {
background: #67c23a;
border-color: #67c23a;
color: #fff;
}
}
.dl-button-info.is-plain {
color: #909399;
background: #d3d4d6;
&:hover,
&:focus {
background: #909399;
border-color: #909399;
color: #fff;
}
}
.dl-button-warning.is-plain {
color: #e6a23c;
background: #f5dab1;
&:hover,
&:focus {
background: #e6a23c;
border-color: #e6a23c;
color: #fff;
}
}
.dl-button-danger.is-plain {
color: #f56c6c;
background: #fbc4c4;
&:hover,
&:focus {
background: #f56c6c;
border-color: #f56c6c;
color: #fff;
}
}
第五步:至此就完成了对于按钮样式的设置,查看一下效果

3.3button组件的round属性
设置round属性和之前的相似,只要在组件中定义好了样式,动态获取属性值即可
获取属性值:
round: {
type: Boolean,
defalut: false
}
round样式:
.dl-button.is-round {
border-radius: 20px;
padding: 12px 23px;
}
效果图:
3.4button组件的circle属性
circle同样是上面的方法,样式为:
.dl-button.is-circle{
border-radius: 50%;
padding: 12px;
}
3.5button组件中使用字体图标
在项目中使用字体图标,首先要字体图标,我们可以去阿里巴巴矢量图标库下载
下载完成后,在asset目录下新建一个fonts目录,存放我们下载到的字体图标。

做完准备工作后,我们就可以开始把字体图标运用到项目中了。
第一步:在main.js中引入字体图标
import './assets/fonts/iconfont.css'
第二步:将下载的字体图标css文件中的类名做修改,我将icon全部改为了dl-icon,并且将初识的iconfont类改为了[class*='dl-icon'],当类名中有dl-icon时使用,如下:
[class*='dl-icon'] {
font-family: 'iconfont' !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.dl-icon-bluetoothoff:before {
content: "\e697"
}
第三步: 父组件传递图标名,子组件接收并且放到图标中
父组件传值:
<div class="row">
<dl-button icon="bluetoothon"></dl-button>
<dl-button type="primary" icon="camera">照相机</dl-button>
<dl-button type="success" icon="course"></dl-button>
<dl-button type="info" icon="bluetooth_link"></dl-button>
<dl-button type="danger" icon="addto"></dl-button>
<dl-button type="warning" icon="audio"></dl-button>
</div>
子组件接收:
icon: {
type: String,
default: ''
}
使用接收到的字体图标。在没有传入icon时隐藏<i>标签,在slot插槽没有传入值时,不显示<span>标签
<template>
<button class="dl-button" :class="[`dl-button-${type}`, {
'is-plain': plain,
'is-round': round,
'is-circle': circle
}]">
<i v-if="icon" :class="`dl-icon-${icon}`"></i>
<!--如果没传入文本插槽,则不显示span内容-->
<span v-if="$slots.default"><solt></solt></span>
</button>
</template>
第四步:设置icon配套样式,使图标和文字之间有一定间隔
.dl-button [class*=dl-icon-]+span {
margin-left: 5px;
}
第五步:查看效果

3.6button组件中的点击事件
我们在使用组件时,直接给组件定义事件是不会被触发的。我们需要在组件中定义一个点击事件,这个点击事件不进行其他操作,只触发父组件的点击事件。
组件中的定义点击事件:
<template>
<button class="dl-button" :class="[`dl-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
}]"
@click="handleClick"
>
<i v-if="icon" :class="`dl-icon-${icon}`"></i>
<!-- 如果没传入文本插槽,则不显示span内容 -->
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
定义一个点击事件,这个点击事件的作用是调用父组件中的点击事件,并且回调
methods: {
handleClick(e) {
this.$emit('click', e)
}
}
父组件在使用时定义自己的点击事件,其本质是子组件中的点击事件触发父组件中的点击事件。
<div class="row">
<dl-button @click="getInfo">按钮</dl-button>
</div>
methods: {
getInfo () {
console.log('获取信息!!')//获取信息!!
}
}
3.7button组件中的disabled属性
和之前相似,只要父子组件传值并且动态获取这个值并且赋值给disabled属性,并且设置一个disabled样式即可
<div class="row">
<dl-button @click="getInfo" disabled>按钮</dl-button>
</div>
<template>
<button class="dl-button" :class="[`dl-button-${type}`,{
'is-plain':plain,
'is-round':round,
'is-circle':circle,
'is-disabled': disabled
}]"
@click="handleClick"
:disable="disabled"
>
<i v-if="icon" :class="`dl-icon-${icon}`"></i>
<!-- 如果没传入文本插槽,则不显示span内容 -->
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
disabled: {
type: Boolean,
default: false
}
disabled样式:
.dl-button.is-disabled {
cursor: no-drop
}
更多推荐


所有评论(0)