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;
		  },
相关推荐
学不会•1 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS2 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
Random_index3 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年6 小时前
react中useMemo的使用场景
前端·react.js·前端框架