撸一个弹窗组件
新建confirm.vue文件
使用vue3里面新出的teleport标签来构建页面
这里text,confirmBtnText,cancelBtnText三个变量由父组件传入。
text
:弹窗的文本信息;
confirmBtnText
:确认按钮的文本信息;
cancelBtnText
:取消按钮的文本信息;
<template>
<!-- 对话框组件 -->
<teleport to="body">
<transition name="confirm-fade">
<div class="confirm" v-show="visible">
<div class="confirm-wrapper">
<div class="confirm-content">
<p class="text">{{ text }}</p>
<div class="operate">
<div class="operate-btn left" @click="confirm">
{{ confirmBtnText }}
</div>
<div class="operate-btn" @click="cancel">
{{ cancelBtnText }}
</div>
</div>
</div>
</div>
</div>
</transition>
</teleport>
</template>
- css样式
这里主要是定义confirm的过渡动画。
<style scoped lang="scss">
.confirm {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 996;
background-color: $color-background-d;
&.confirm-fade-enter-active {
animation: confirm-fadein .3s;
.confirm-content {
animation: confirm-zoom-in .3s;
}
}
&.confirm-fade-leave-active {
animation: confirm-fadeout .3s;
.confirm-content {
animation: confirm-zoom-out .3s;
}
}
.confirm-wrapper {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 997;
.confirm-content {
width: 270px;
border-radius: 13px;
background: $color-highlight-background;
.text {
padding: 19px 15px;
line-height: 22px;
text-align: center;
font-size: $font-size-large;
color: $color-text-l;
}
.operate {
display: flex;
align-items: center;
text-align: center;
font-size: $font-size-large;
.operate-btn {
flex: 1;
line-height: 22px;
padding: 10px 0;
border-top: 1px solid $color-background-d;
color: $color-text-l;
&.left {
border-right: 1px solid $color-background-d;
color: $color-text;
}
}
}
}
}
@keyframes confirm-fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes confirm-fadeout {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes confirm-zoom-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
@keyframes confirm-zoom-out {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
}
</style>
- 下面开始撸业务逻辑
定义个props用来接收父组件传来的值。
export default {
name: 'confirm',
props: {
text: {
type: String,
default: ''
},
confirmBtnText: {
type: String,
default: '确定'
},
cancelBtnText: {
type: String,
default: '取消'
}
},
......
}
定义data里面的变量visible来控制弹窗的出现和消失。
export default {
......
data () {
return {
visible: false
}
}
.....
}
定义几个事件来完成这个组件。
confirm ()
:点击确认按钮,隐藏组件,并向父组件派发confirm事件;
cancel ()
:点击取消按钮,隐藏组件,并向父组件派发cancel事件;
hide ()
:隐藏组件;
show ()
:显示组件;
使用emits
将这两个事件派发出去。
export default {
......
emits: ['confirm', 'cancel'],
methods: {
// 确认
confirm () {
this.hide()
this.$emit('confirm')
},
// 取消
cancel () {
this.hide()
this.$emit('cancel')
},
hide () {
this.visible = false
},
show () {
this.visible = true
}
}
}
- 组件使用
引用组件,拿到组件的ref,并定义一个confirm事件,来控制点击确定后面要干的事情。text,confirmBtnText控制组件显示的文本信息。
<confirm
ref="confirmRef"
@confirm="confirm"
text="是否清空播放列表"
confirmBtnText="清空"
></confirm>
在使用组件的按钮处定义@click事件,来唤起组件让其显示。
<span class="clear" @click="showConfirm">
<i class="icon-clear"></i>
</span>
业务逻辑这里使用setup函数组合API来编写。
先用ref拿到组件的dom
import { ref } from 'vue'
import Confirm from '../base/confirm/confirm'
export default {
......
setup () {
// 拿到confirm的dom
const confirmRef = ref(null)
// 唤起confirm
function showConfirm () {
confirmRef.value.show()
}
// 点击确认按钮后的事件处理
function confirm () {
...
这里编写你自己的处理逻辑
...
// 事件处理完后记得关闭confirm组件
confirmRef.value.hide()
}
return {
confirmRef,
showConfirm,
confirm
}
}
......
}
- END 结束