一、vue 实现 ui 组件库之 Dialog 组件
- 在项目的
文件夹中,建立components
文件,在dialog.vue
中,先写对话框的遮罩,并且在遮罩外使用template
动画进行包裹,定义对话框的动画效果。在对话框的遮罩中,使用transition
命令控制v-show
的值,来控制对话框的显示与隐藏。通过visible
绑定点击事件@click
,对话框的关闭事件,通过使用handleClose
修饰符,只有当点击自己的时候才会被触发。对话框的显示标题使用.self
属性,旁边的关闭按钮也通过title
绑定点击事件@click
。对于对话框的中间显示内容部分,使用默认插槽handleClose
。对于对话框的底部,使用具名插槽为slot
,同时使用footer
命令判断v-if
,有插槽$slots.footer
就显示,没有就不显示,代码如下所示:footer
<transition name="dialog-fade">
<div class="jc-dialog__wrapper" v-show="visible" @click.self="handleClose">
<div class="jc-dialog" :style="{width, marginTop:top}">
<div class="jc-dialog__header">
<slot name="title">
<span class="jc-dialog__title">{{ title }}</span>
</slot>
<button class="jc-dialog__headerbtn" @click="handleClose">
<i class="jc-icon-close"></i>
</button>
</div>
<div class="jc-dialog__body">
<slot></slot>
</div>
<div class="jc-dialog__footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</transition>
- 在
中,定义script
的值为name
。定义JcDialog
,定义props
为title
类型,默认显示为提示;定义String
为width
类型,默认显示为String
;定义50%
为top
类型,默认显示为String
;定义15vh
为visible
类型,默认显示为Boolean
。在false
中,定义methods
对话框的关闭事件,通过handleClose
向父组件传递this.$emit
事件,传递值为update:visible
,使用false
这种写法是为了后面使用update:visible
修饰符,代码如下随所示:sync
<script>
export default {
name: 'JcDialog',
props: {
title: {
type: String,
default: '提示'
},
width: {
type: String,
default: '50%'
},
top: {
type: String,
default: '15vh'
},
visible: {
type: Boolean,
default: false
}
},
methods: {
handleClose () {
this.$emit('update:visible', false)
}
}
}
</script>
- 这个
按钮组件的参数支持,如下所示:Dialog
参数名 | 参数描述 | 参数类型 | 默认值 |
---|---|---|---|
title | 对话框标题 | string | 提示 |
width | 宽度 | string | 50% |
top | 与顶部的距离 | string | 15vh |
visible | 是否显示dialog(支持sync修饰符) | boolean | false |
- 在
中,写对话框的一些样式,style
是使用::v-deep
中的深度选择器。定义scss
动画@keyframes
,进行显示与隐藏。在fade
中对话框进入的动画,在.dialog-fade-enter-active
中对话框离开的动画,代码如下所示:.dialog-fade-leave-active
<style lang="scss" scoped>
.jc-dialog__wrapper {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
margin: 0;
z-index: 2001;
background-color: rgba(0,0,0, .5);
.jc-dialog {
position: relative;
margin: 15vh auto 50px;
background: #fff;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0,0,0,.3);
box-sizing: border-box;
width: 30%;
&__header {
padding: 20px 20px 10px;
.jc-dialog__title {
line-height: 24px;
font-size: 18px;
color: #303133;
}
.jc-dialog__headerbtn {
position: absolute;
top: 20px;
right: 20px;
padding: 0;
background: transparent;
border: none;
outline: none;
cursor: pointer;
font-size: 16px;
.el-icon-close {
color: #909399;
}
}
}
&__body {
padding: 30px 20px;
color: #606266;
font-size: 14px;
word-break: break-all;
}
&__footer {
padding: 10px 20px 20px;
text-align: right;
box-sizing: border-box;
::v-deep .jc-button:first-child {
margin-right: 20px;
}
}
}
}
.jc-button {
margin-right: 20px;
}
.dialog-fade-enter-active {
animation: fade .3s;
transform: translateY(-20px);
}
.dialog-fade-leave-active {
animation: fade .3s reverse;
transform: translateY(0px);
}
@keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>
- 在
文件中,引入main.js
组件,并且进行全局注册组件,代码如下所示:JcDialog
import JcDialog from './components/dialog.vue'
Vue.component(JcDialog.name, JcDialog)
- 在
文件中,使用App.vue
组件,在dialog
中,定义data
的值为visible
。先使用false
按钮组件,控制对话框的显示与隐藏,绑定点击事件,将jc-button
的值变为visible
,对话框显示。在true
中,分别设置jc-dialog
、title
和width
的值,使用top
,也就是:visible.sync
修饰符,将子组件传递的sync
的值赋值为false
,对话框就会由显示变为隐藏。visible
是对话框中间显示的内容,使用ul
,名为template
的插槽,定义两个按钮,绑定点击事件,将footer
变为visible
,对话框进行隐藏,代码如下所示:false
<template>
<div id="app">
<jc-button type="primary" @click="visible = true">按钮</jc-button>
<jc-dialog title="温馨提示" width="20%" top="200px" :visible.sync="visible">
<ul>
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
<template v-slot:footer>
<jc-button type="primary" @click="visible = false">确定</jc-button>
<jc-button type="primary" @click="visible = false">取消</jc-button>
</template>
</jc-dialog>
</div>
</template>
<script>
export default {
data () {
return {
visible: false
}
}
}
</script>
<style lang="scss">
.row {
margin-bottom: 20px;
.jc-button {
margin-right: 20px !important;
}
}
</style>
- 在浏览器中输入
,显示如下所示:http://localhost:8080/
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB1ENBRkT4llaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zROBlL3AzM0MzM1EjMxATNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)