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;
		  },
相关推荐
~甲壳虫44 分钟前
react中得类组件和函数组件有啥区别,怎么理解这两个函数
前端·react.js·前端框架
.net开发1 小时前
WPF使用Prism框架首页界面
前端·c#·.net·wpf
名字越长技术越强1 小时前
vue--vueCLI
前端·javascript·vue.js
是个热心市民1 小时前
构建一个导航栏web
前端·javascript·python·django·html
J不A秃V头A2 小时前
报错:npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。
前端·npm·node.js
GDAL2 小时前
npm入门教程14:npm依赖管理
前端·npm·node.js
余生H2 小时前
即时可玩web小游戏(二):打砖块(支持移动端版) - 集成InsCode快来阅读并即时体验吧~
前端·javascript·inscode·canvas·h5游戏
5335ld2 小时前
vue+exceljs前端下载、导出xlsx文件
前端·vue.js
摇头的金丝猴2 小时前
uniapp vue3 使用echarts-gl 绘画3d图表
前端·uni-app·echarts
清清ww2 小时前
【TS】九天学会TS语法---计划篇
前端·typescript