文章来源地址https://www.toymoban.com/news/detail-811454.html
写了一个弹框组件
<template>
<transition name="modal-fade">
<div v-if="showFlag" class="myModal">
<div class="content">
<div class="topBox">
<div class="leftTitle">
<span>{{ title }}</span>
</div>
<div class="rightClose" @click="cancelModal"><CloseOutlined /></div>
</div>
<slot name="content"></slot>
</div>
</div>
</transition>
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
const props = defineProps({
title: {
type: String,
default: '',
},
})
const { title } = toRefs(props)
// 是否开启弹框
let showFlag = ref(false)
// 开启
const showModal = () => {
showFlag.value = true
}
// 关闭
const cancelModal = () => {
showFlag.value = false
}
defineExpose({
showModal,
cancelModal,
})
</script>
<style lang="less" scoped>
// 这个动画是,打开弹框时,有一个缓慢打开的效果
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
// 打开弹框时给它一个上下抖动的效果
@keyframes shake {
0% { transform: translateY(0); }
25% { transform: translateY(-10px); }
50% { transform: translateY(0); }
75% { transform: translateY(10px); }
100% { transform: translateY(0); }
}
.myModal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
z-index: 100;
animation: fadeIn 0.5s;
// animation: fadeIn 0.5s, shake 0.5s;
.content {
position: absolute;
left: 50%;
top: 30%;
transform: translate(-50%, -50%);
background: #ffffff;
width: 500px;
padding: 10px;
.topBox {
display: flex;
height: 30px;
border-bottom: 1px solid #f0f0f0;
padding: 0 10px 0 0;
margin-bottom: 20px;
cursor: pointer;
.leftTitle {
flex: 1;
text-align: left;
color: rgba(0, 0, 0, 0.8);
font-weight: 600;
font-size: 16px;
}
.rightClose {
flex: 1;
text-align: right;
}
}
}
}
// start - 效果为:关闭时,有一个缓慢消失的效果
.modal-fade-enter-active, .modal-fade-leave-active {
transition: opacity 0.5s;
}
.modal-fade-enter, .modal-fade-leave-to {
opacity: 0;
}
// end - 效果为:关闭时,有一个缓慢消失的效果
</style>
使用它
<template>
<MyModal ref="myModal" :title="title">
<template #content>
<div style="display: grid; place-items: center">
<a-form ref="loginForm" :model="formState" :label-col="labelCol" style="width: 360px">
<a-form-item has-feedback name="userName">
<a-input v-model:value="formState.phone" placeholder="请输入手机号" autocomplete="off">
<template #prefix><UserOutlined style="color: rgba(0, 0, 0, 0.25)" /></template>
</a-input>
</a-form-item>
<a-form-item has-feedback name="code">
<a-input
v-model:value="formState.code"
placeholder="验证码"
autocomplete="off"
style="width: 240px"
>
<template #prefix><MailOutlined style="color: rgba(0, 0, 0, 0.25)" /></template>
</a-input>
<a-button
:disabled="myState.smsSendFlag"
v-text="(!myState.smsSendFlag && '获取验证码') || `${myState.time} s`"
@click="getSms"
style="margin-left: 15px"
type="primary"
></a-button>
</a-form-item>
<a-form-item style="text-align: center">
<a-button style="width: 360px" type="primary" block @click="handleSubmit">
登录
</a-button>
</a-form-item>
</a-form>
</div>
</template>
</MyModal>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import * as accountApi from '@/api/account'
import MyModal from '@/components/MyModal/MyModal.vue'
import { message } from 'ant-design-vue'
const myModal = ref()
const showModal = () => {
myModal.value?.showModal()
}
defineExpose({
showModal,
})
let title = ref('x管家登陆')
const myState = reactive({
smsSendFlag: false,
time: 60,
})
let labelCol = { span: 4 }
interface formState {
phone: string | number
code: string | number
}
const formState = ref<formState>({
phone: '',
code: '',
})
// 获取验证码
const getSms = async () => {
let params = {
phone: formState.value.phone,
}
if (params['phone'] == '') {
message.error(`手机号不能为空~`)
return
}
const hide = message.loading('验证码发送中..', 0)
try {
let { state, message: msg } = await accountApi.idleSendSms(params)
if (state === 200) {
myState.smsSendFlag = true
const interval = setInterval(() => {
if (myState.time-- <= 0) {
myState.time = 60
myState.smsSendFlag = false
clearInterval(interval)
}
}, 1000)
} else {
message.error(msg)
}
} catch (error) {
message.error('网络请求连接失败~')
}
setTimeout(hide, 1)
}
// 登录
const handleSubmit = async () => {
let params = {
phone: formState.value.phone,
code: formState.value.code,
}
try {
const { state, message: msg, token } = await accountApi.idleLogin(params)
if (state === 200) {
message.success('登录成功~')
myModal.value?.cancelModal()
} else {
message.error(msg)
}
} catch (error) {
message.error('网络请求发送失败~')
}
}
</script>
文章来源:https://www.toymoban.com/news/detail-811454.html
到了这里,关于vue3 - 自定义弹框组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!