uni-app自定义弹窗

1、项目根目录components目录下创建/modal/modal.vue文件

2、modal.vue文件内容

vue2版本:

<template>
	<view class="modal-container">
		<view class="bg" @tap="maskClose"></view>
		<view class="box">
			<view class="content-box">
				<slot></slot>
			</view>
			<view class="footer">
				<view v-if="cancelVisble" class="item-cancel" @tap="cancel">{{cancelText}}</view>
				<view :class="['item-ok',{'ghost':okGhost}]" @tap="ok">{{okText}}</view>
			</view>
			<view v-if="closable" class="close-btn" @tap="close">
				<image v-if="closeImg" :src="imgs" class="icon-close"></image>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		name:"modal",
		data(){
			return {
				// 取消按钮文字
				cancelText:"取消",
				// 	取消按钮是否显示
				cancelVisble:true,
				// 确认按钮文字
				okText:"确定",
				// 幽灵属性,使按钮背景透明
				okGhost:false,
				// 点击蒙层是否允许关闭
				maskClosable:true,
				// 是否显示关闭按钮
				closable:true,
				closeImg:false,
				imgs:'https://frontend-c.oss-cn-hangzhou.aliyuncs.com/wz-mini-program/v2/icons/close.png'
			}
		},
		props:[
			// 取消按钮文字
			'cancelTextMethod',
			// 	取消按钮是否显示
			'cancelVisbleMethod',
			// 确认按钮文字
			'okTextMethod',
			// 幽灵属性,使按钮背景透明
			'okGhostMethod',
			// 点击蒙层是否允许关闭
			'maskClosableMethod',
			// 是否显示关闭按钮
			'closableMethod',
		],
		onMounted() {
			this.$emit(['cancel','ok']);
		},
		methods:{
			maskClose(){
				if(props.maskClosable){
					// console.log("maskClose")
					this.$emit("cancel")
				}
			},
			close(){
				// console.log("close")
				this.$emit("cancel")
			},
			cancel(){
				// console.log("cancel")
				this.$emit("cancel")
			},
			ok(){
				// console.log("ok")
				this.$emit("ok")
			}
		}
	}
</script>
<style lang="scss" scoped>
	.modal-container{
		position: fixed;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		z-index: 103;
		background-color: rgba(0, 0, 0, 0.6);
		.bg{
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
		}
		.box{
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%,-50%);
			min-width: 590rpx;
			min-height: 338rpx;
			background: #FFFFFF;
			border-radius: 22rpx;
			padding: 90rpx 26rpx 50rpx;
			box-sizing: border-box;
			display: flex;
			flex-direction: column;
			.content-box{
				flex: 1;
				text-align: center;
				font-family: PingFangSC, PingFang SC;
				font-weight: 500;
				font-size: 34rpx;
				color: #222222;
			}
			.footer{
				padding-top: 20rpx;
				box-sizing: border-box;
				display: flex;
				gap: 0 20rpx;
				.item-cancel,.item-ok{
					flex: 1;
					height: 80rpx;
					border-radius: 40rpx;
					border: 1rpx solid #979797;
					transform: rotateZ(360deg);
					display: flex;
					align-items: center;
					justify-content: center;
					font-family: PingFangSC, PingFang SC;
					font-weight: 400;
					font-size: 34rpx;
				}
				.item-cancel{
					background: #FFFFFF;
					color: #000000;
				}
				.item-ok{
					background: linear-gradient( 90deg, #77C708 0%, #34B834 100%);
					color: #FFFFFF;
					border-color: transparent;
					&.ghost{
						border-color: #1FA71F;
						background: #FFFFFF;
						color: #1FA71F;
					}
				}
			}
			.close-btn{
				position: absolute;
				bottom: -174rpx;
				left: 50%;
				z-index: 2;
				transform: translateX(-50%);
				padding: 40rpx;
				box-sizing: border-box;
				.icon-close{
					width: 64rpx;
					height: 64rpx;
				}
			}
		}
	}
</style>

vue3版本:

<template>
	<view class="modal-container">
		<view class="bg" @tap="maskClose"></view>
		<view class="box">
			<view class="content-box">
				<slot></slot>
			</view>
			<view class="footer">
				<view v-if="cancelVisble" class="item-cancel" @tap="cancel">{{cancelText}}</view>
				<view :class="['item-ok',{'ghost':okGhost}]" @tap="ok">{{okText}}</view>
			</view>
			<view v-if="closable" class="close-btn" @tap="close">
				<image :src="config.imgs[0]" class="icon-close"></image>
			</view>
		</view>
	</view>
</template>

<script setup>
	defineOptions({ name: 'Modal' });
	const emit = defineEmits(['cancel','ok'])
	const props = defineProps({
		// 取消按钮文字
		cancelText:{
			type:String,
			default:"取消"
		},
		// 	取消按钮是否显示
		cancelVisble:{
			type:Boolean,
			default:true
		},
		// 确认按钮文字
		okText:{
			type:String,
			default:"确定"
		},
		// 幽灵属性,使按钮背景透明
		okGhost:{
			type:Boolean,
			default:false
		},
		// 点击蒙层是否允许关闭
		maskClosable:{
			type:Boolean,
			default:true
		},
		// 是否显示关闭按钮
		closable:{
			type:Boolean,
			default:true
		},
	})
	import {
		ref,
		reactive,
		computed,
		onMounted
	} from 'vue'
	const config = reactive({
		imgs:[
			'https://frontend-c.oss-cn-hangzhou.aliyuncs.com/wz-mini-program/v2/icons/close.png'
		]
	})
	
	const maskClose=()=>{
		if(props.maskClosable){
			// console.log("maskClose")
			emit("cancel")
		}
	}
	
	const close =()=>{
		// console.log("close")
		emit("cancel")
	}
	
	const cancel =()=>{
		// console.log("cancel")
		emit("cancel")
	}
	
	const ok =()=>{
		// console.log("ok")
		emit("ok")
	}
	
	
	onMounted(()=>{
		
	})
	
</script>

<style lang="scss" scoped>
	.modal-container{
		position: fixed;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		z-index: 103;
		background-color: rgba(0, 0, 0, 0.6);
		.bg{
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
		}
		.box{
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%,-50%);
			min-width: 590rpx;
			min-height: 338rpx;
			background: #FFFFFF;
			border-radius: 22rpx;
			padding: 90rpx 26rpx 50rpx;
			box-sizing: border-box;
			display: flex;
			flex-direction: column;
			.content-box{
				flex: 1;
				text-align: center;
				font-family: PingFangSC, PingFang SC;
				font-weight: 500;
				font-size: 34rpx;
				color: #222222;
			}
			.footer{
				padding-top: 20rpx;
				box-sizing: border-box;
				display: flex;
				gap: 0 20rpx;
				.item-cancel,.item-ok{
					flex: 1;
					height: 80rpx;
					border-radius: 40rpx;
					border: 1rpx solid #979797;
					transform: rotateZ(360deg);
					display: flex;
					align-items: center;
					justify-content: center;
					font-family: PingFangSC, PingFang SC;
					font-weight: 400;
					font-size: 34rpx;
				}
				.item-cancel{
					background: #FFFFFF;
					color: #000000;
				}
				.item-ok{
					background: linear-gradient( 90deg, #77C708 0%, #34B834 100%);
					color: #FFFFFF;
					border-color: transparent;
					&.ghost{
						border-color: #1FA71F;
						background: #FFFFFF;
						color: #1FA71F;
					}
				}
			}
			.close-btn{
				position: absolute;
				bottom: -174rpx;
				left: 50%;
				z-index: 2;
				transform: translateX(-50%);
				padding: 40rpx;
				box-sizing: border-box;
				.icon-close{
					width: 64rpx;
					height: 64rpx;
				}
			}
		}
	}
</style>

3、使用方法

import Modal from '@/components/modal/modal.vue';// 在所需*.vue中引用

<template>		
    <view>
        ****
        ****
        <!--自定义弹窗-->
		<modal v-if="isShowAdTip" :cancelVisbleMethod="true" @cancel="cancel" @ok="ok">确定添加要素点么?</modal>
	</view>
	
</template>

data(){
	return {
		isShowAdTip:false,
        ***
    }
},

          cancel(){// 自定义弹窗取消按钮事件
		   	//console.log("cancel回调")
		   	this.isShowAdTip = false;
		  },
		  ok(){// 自定义弹窗确定按钮事件
		   	//console.log("ok回调")
		   	this.isShowAdTip = false;
		   	// 传递信息新增要素点
		   	this.valueChangeSign.type= "ADDNEWFEATURE";
		   	this.valueChangeSign.flag = !that.valueChangeSign.flag;
		  },
相关推荐
前端没钱22 分钟前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
汪洪墩27 分钟前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
NoneCoder27 分钟前
CSS系列(29)-- Scroll Snap详解
前端·css
无言非影31 分钟前
vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)
前端·css
我曾经是个程序员1 小时前
鸿蒙学习记录
开发语言·前端·javascript
羊小猪~~1 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
摸鱼了1 小时前
🚀 从零开始搭建 Vue 3+Vite+TypeScript+Pinia+Vue Router+SCSS+StyleLint+CommitLint+...项目
前端·vue.js
程序员shen1616112 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
Ling_suu2 小时前
SpringBoot3——Web开发
java·服务器·前端
Yvemil72 小时前
《开启微服务之旅:Spring Boot Web开发》(二)
前端·spring boot·微服务