uniapp全局弹窗(APP端)

news2025/1/27 12:08:39

 uniapp自带的提示框不符合我们的要求,需要自己写一个提示框,且全局通用。

解决思路: 使用 plus.nativeObj 来绘制窗口以及事件监听。    官方文档

1. 首先创建一个整个屏幕的控件,作为一个父容器。 此时还看不到任何东西

let screenHeight = uni.getSystemInfoSync().screenHeight;
let style = {
    width:'100%',
    height: (screenHeight + 'px'),
    left:'0px',
    top:'0px'
};

// 创建原生控件对象
// 参数1: id
// 参数2: 控件的样式
let view = new plus.nativeObj.View('showModalView',style);

2. 绘制遮罩层

view.draw([
	{tag:'rect',id:'modal',color:`rgba(0,0,0,0.4)`,position:{top:'0px',left:'0px',width:'100%',height:'100%'}}
]);


{
    tag:'rect',                        // 绘制矩形
    id:'modal',                        // 控件id
    color:`rgba(0,0,0,0.4)`,            // 背景色
    position:{top:'0px',left:'0px',width:'100%',height:'100%'}        // 位置和大小样式
}

view.draw(tags); 在控件上绘制,传入绘制对象。

绘制对象文档 可绘制图片、矩形区域、文本等内容。  

3.绘制通知框样式

view.draw([
	{tag:'rect',id:'modal',color:`rgba(0,0,0,0.4)`,position:{top:'0px',left:'0px',width:'100%',height:'100%'}},
    {tag:'rect',id:'content',rectStyles:{borderWidth:'2px',radius:'8px',color:`rgba(36,34,56,1)`},position:{top:startTop+'px',left:startLeft+'px',width:width+'px',height:height+'px'}},
]);

{
    tag:'rect',
    id:'content',
    // 矩形的样式
    rectStyles:{borderWidth:'2px',radius:'8px',color:`rgba(36,34,56,1)`},
    // 位置和大小. 下面的变量是根据屏幕宽高手动计算的
    position:{top:startTop+'px',left:startLeft+'px',width:width+'px',height:height+'px'}
}

interface RectStyles {
	attribute String color;
	attribute String radius;
	attribute String borderColor;
	attribute String borderWidth;
}	

4. 绘制标题和内容

view.draw([
	{tag:'rect',id:'modal',color:`rgba(0,0,0,0.4)`,position:{top:'0px',left:'0px',width:'100%',height:'100%'}},
    {tag:'rect',id:'content',rectStyles:{borderWidth:'2px',radius:'8px',color:`rgba(36,34,56,1)`},position:{top:startTop+'px',left:startLeft+'px',width:width+'px',height:height+'px'}},
    {tag:'font',id:'title',text:modelInfo.tit,textStyles:{size:'16px',color:'#fff'},position:{top:titleTop+'px',left:startLeft+'px',width:width+'px',height:titleHeight+'px'}},
	{tag:'font',id:'text',text:modelInfo.content,textStyles:{size:'14px',color:'#fff',whiteSpace:'normal',align:modelInfo.align},position:{top:contentTop+'px',left:startLeft+'px',width:width+'px',height:contentHeight+'px'}},
    // 这个是内容和底部按钮的分割线
	{tag:'rect',id:'line',color:'rgba(255,255,255,0.3)',position:{top:lineTop+'px',left:startLeft+'px',width:width+'px',height:'0.5px'}},
]);

{
    tag:'font',                    // 绘制文字
    id:'title',
    text:modelInfo.tit,            // 文字内容
    textStyles:{size:'16px',color:'#fff'},
    position:{top:titleTop+'px',left:startLeft+'px',width:width+'px',height:titleHeight+'px'}
},

5. 创建确认按钮控件

我们需要给确认按钮设置点击事件,所以它要作为一个新的控件,而不是再刚刚的控件上继续绘制。

// 确认
let viewconfirm=new plus.nativeObj.View('confirm',
	{
		width:modelInfo.delCancel?width+'px':'40%',
		height:buttonHeight+'px',
		top:lineTop+'px',
		left:modelInfo.delCancel?startLeft+'px':halfWidthForGlobal +'px',
		backgroundColor:'rgba(255,255,255,0)',
	},
);
viewconfirm.draw([
	{tag:'font',id:'confirm',text:modelInfo.confirmVal,textStyles:{color:modelInfo.confirmColor,size:'14px'}},
]);

设置点击事件

viewconfirm.addEventListener("click",(e)=>{
    // 发送事件
	this.$event({res:true,types:'confirm'});
    // 隐藏当前控件(关闭)
	this.hide();
},false);

将 viewconfirm和view显示出来:

function show(){
    this.view.show();
    this.confirmModel.show();
}

下面就是将这些挂载到Uni上就可以了。

下面是项目中的完整代码:

index.js 用于绘制

// show_modal/index.js
export class show_model{
	constructor(option={}) {
		this.bodyModel=null;
		this.cancelModel=null;
		this.confirmModel=null;
		this.pageHeight=uni.getSystemInfoSync().screenHeight;
		this.pageWidth = uni.getSystemInfoSync().screenWidth;
		let opacity = option.opacity || 0.4;
		let model_tit=option.title||'温馨提示';
		let model_content=option.content||"内容"
		let clickEvent=option.IsclickEvent||false;
		let cancelVal=option.cancelVal||'取消';
		let confirmVal=option.confirmVal||'确认';
		let cancelColor=option.cancelColor||'#fff';				// 取消
		let confirmColor=option.confirmColor||'#fff';			// 确认
		let delCancel=option.delCancel||false;
		let align=option.align||"center";
		let fn = ()=>{};
		this.$event = option.$event || fn;
		let backOff=option.backOff||false;
		
		//#ifdef APP-PLUS
		this.creatView({height:`${this.pageHeight}px`,top:0},opacity,clickEvent,{'tit':model_tit,'content':model_content,cancelVal,confirmVal,confirmColor,cancelColor,delCancel,align})
		if(!backOff){
			this.backbtn();
		}
		//#endif
	}
    backbtn(){
		let that=this;
		plus.key.addEventListener('backbutton', function (e) {
			that.hide();
		},false)
	}
	//生成提示框view
	creatView(style,opa,clickEvent,modelInfo){
		style = {
			left:'0px',
			width:'100%',
			...style
		}
        let platform = plus.os.name.toLowerCase();
		let view = new plus.nativeObj.View('showModalView',style);
		
		let width = 300;
		let height = 150;
		let titleHeight = 20;
		let contentHeight = 60;
		let startTop = (this.pageHeight - height) / 2;
		let startLeft = (this.pageWidth - width) / 2;
		let titleTop = startTop + 10;
		let contentTop = titleTop+30;
		let lineTop = startTop + height - 40;
		let buttonHeight = 40;
		let halfWidth = width / 2;
		let halfWidthForGlobal = startLeft + halfWidth;
		
		if(platform == "ios"){
			view.draw([
				{tag:'rect',id:'modal',color:`rgba(0,0,0,${opa})`,position:{top:'0px',left:'0px',width:'100%',height:'100%'}},
			    {tag:'rect',id:'content',rectStyles:{borderWidth:'2px',radius:'8px',color:`rgba(36,34,56,1)`},position:{top:startTop+'px',left:startLeft+'px',width:width+'px',height:height+'px'}},
			    {tag:'font',id:'title',text:modelInfo.tit,textStyles:{size:'16px',color:'#fff'},position:{top:titleTop+'px',left:startLeft+'px',width:width+'px',height:titleHeight+'px'}},
			    {tag:'font',id:'text',text:modelInfo.content,textStyles:{size:'14px',color:'#fff',whiteSpace:'normal',align:modelInfo.align},position:{top:contentTop+'px',left:startLeft+'px',width:width+'px',height:contentHeight+'px'}},
			    {tag:'rect',id:'line',color:'rgba(255,255,255,0.3)',position:{top:lineTop+'px',left:startLeft+'px',width:width+'px',height:'0.5px'}},
				{tag:'rect',id:'line2',color:'rgba(255,255,255,0.3)',position:{top:lineTop+'px',left:+halfWidthForGlobal+'px',width:modelInfo.delCancel?'0px':'0.5px',height:modelInfo.delCancel?'0px':buttonHeight+'px'}}
			]);
		}else{
			view.draw([
				{tag:'rect',id:'modal',color:`rgba(0,0,0,${opa})`,position:{top:'0px',left:'0px',width:'100%',height:'100%'}},
			    {tag:'rect',id:'content',rectStyles:{borderWidth:'2px',radius:'8px',color:`rgba(36,34,56,1)`},position:{top:startTop+'px',left:startLeft+'px',width:width+'px',height:height+'px'}},
			    {tag:'font',id:'title',text:modelInfo.tit,textStyles:{size:'16px',color:'#fff'},position:{top:titleTop+'px',left:startLeft+'px',width:width+'px',height:titleHeight+'px'}},
			    {tag:'font',id:'text',text:modelInfo.content,textStyles:{size:'14px',color:'#fff',whiteSpace:'normal',align:modelInfo.align},position:{top:contentTop+'px',left:startLeft+'px',width:width+'px',height:contentHeight+'px'}},
			    {tag:'rect',id:'line',color:'rgba(255,255,255,0.3)',position:{top:lineTop+'px',left:startLeft+'px',width:width+'px',height:'0.5px'}},
				{tag:'rect',id:'line2',color:'rgba(255,255,255,0.3)',position:{top:lineTop+'px',left:halfWidthForGlobal+'px',width:modelInfo.delCancel?'0px':'0.5px',height:modelInfo.delCancel?'0px':buttonHeight+'px'}}
			]);
		}
		
		var num = 0.55;
		if(platform == "ios"){
			num = 0.57
		}
		if(!modelInfo.delCancel){
			// 取消	
			let viewCancel=new plus.nativeObj.View('cancel',{width:halfWidth+'px',height:buttonHeight+'px',top:lineTop+'px',left:startLeft+'px',backgroundColor:'rgba(255,255,255,0)'});
			    viewCancel.draw([
				  {tag:'font',id:'cancel',text:modelInfo.cancelVal,textStyles:{color:modelInfo.cancelColor,size:'14px'}},
				]);
				
				viewCancel.addEventListener("click",(e)=>{
					this.$event({res:false,types:'cancel'});
					this.hide();
				},false);
				this.cancelModel=viewCancel;
		}
		// 确认
		let viewconfirm=new plus.nativeObj.View('confirm',
			{
				width:modelInfo.delCancel?width+'px':'40%',
				height:buttonHeight+'px',
				top:lineTop+'px',
				left:modelInfo.delCancel?startLeft+'px':halfWidthForGlobal +'px',
				backgroundColor:'rgba(255,255,255,0)',
			},
		);
		viewconfirm.draw([
			{tag:'font',id:'confirm',text:modelInfo.confirmVal,textStyles:{color:modelInfo.confirmColor,size:'14px'}},
		]);
	
		viewconfirm.addEventListener("click",(e)=>{
			this.$event({res:true,types:'confirm'});
			this.hide();
		},false);
		  //点击蒙布
		if(clickEvent){
			 view.addEventListener("click", (e) => {
				this.$event({res:false,types:'cover'});
				this.hide();
			}, false);
		}
	   this.bodyModel=view;
	   this.confirmModel=viewconfirm;
	}
    showModalAnimationClose(){
		var options = {type:'pop-out',duration:300};
			plus.nativeObj.View.startAnimation(options,{view:this.bodyModel},{view:this.cancelModel},{view:this.viewconfirm},function(){
				console.log('plus.nativeObj.View.startAnimation动画结束');
				// 关闭原生动画
				plus.nativeObj.View.clearAnimation();
			});
	}
	showModalAnimationOpen(){
		var options = {type:'pop-in',duration:1000};
		
			plus.nativeObj.View.startAnimation(options,{view:this.bodyModel},{view:this.cancelModel},{view:this.viewconfirm},function(){
				console.log('plus.nativeObj.View.startAnimation动画结束');
				// 关闭原生动画
				plus.nativeObj.View.clearAnimation();
			});
	}
	show(){
		this.showModalAnimationOpen();
		this.bodyModel.show();
		if(this.cancelModel){
			this.cancelModel.show();
		}
		this.confirmModel.show();
	
	}
	hide(){
		this.showModalAnimationClose();
		this.bodyModel.hide();
		if(this.cancelModel){
	      this.cancelModel.hide();	
		}
		this.confirmModel.hide();
	}
}

export default show_model

show_modal.js: 用于创建promise对象并挂载

// show_modal/xt_show_modal.js
import show_modal from './index.js'

const xt_show_modal = {
	install: function(Vue) {
        const show_modal_fun=function(op={}){
			//#ifdef APP-PLUS
			return	new Promise((resolve, reject)=>{
			   let ssm=new show_modal({
					...op,
					$event:function(e){
						if(e.res){
							resolve(e);
						}else{
							reject(e);
						}
					 }
				});
				ssm.show();
				Vue.prototype.$hide=function(){
					ssm.hide();
				}
			})
			//#endif
			
            // 适应H5
			//#ifdef H5
				var promise=uni.showModal({
					title: op.title,
					content: op.content,
					showCancel: !op.delCancel,
					cancelText: op.cancelVal,
					confirmText: op.confirmVal,
				});
				
				return new Promise((resolve,reject)=>{
					promise.then(data=>{
						var [err, res] = data;
						if(res.confirm){
							resolve()
						}else{
							reject();
						}
					})
				})
				
			//#endif
            
		}
        // $showModal挂载到uni对象上
        uni.$showModal = show_modal_fun
        Vue.prototype.$showModal = show_modal_fun
	}
};

export default xt_show_modal;

main.js中挂载

// 自定义showModal组件
import xt_show_modal from '@/component/show_modal/xt_show_modal.js'
Vue.use(xt_show_modal);

使用:

// showModel的使用
uni.$showModal({
	title:"",				//可选,不填则不显示
    content:'未知错误,请联系管理员!',
    delCancel: true,
    confirmVal: '知道了',	// 可选
	cancelVal:'取消',		// 可选
}).then(res=>{
	// 点击确认按钮点击事件
}).catch(res=>{
	// 点击取消按钮点击事件
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

牛客网前端刷题(二)

还在担心面试不通过吗?给大家推荐一个超级好用的刷面试题神器:牛客网,里面涵盖了各个领域的面试题库,还有大厂真题哦! 赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏…

微信小程序之开发遇到 does not have a method “xxxx“ to handle event “tap“ 问题的解决方案【已解决】

今天在开发一个小功能,copy了之前写的代码,但是在实现功能时,出现了如下问题: 先在这简单总结一下解决方案: 在调用方法时,在" "中前后多加了空格;在 js 中没有定义该方法&#xff1…

纯前端导出表格

前端 excel 表格导出 我们习惯了后端去处理表格,直接接口返回 ,那前端如何轻松的导出表格呢? 文章目录前端 excel 表格导出Ⅰ. 通过 js-xlsx ⭐⭐⭐⭐⭐安装① vue2 中使用② vue3 中使用③ react 中使用Ⅲ. 通过 vue-json-excel ⭐⭐安装使…

SpringBoot--Filter过滤器(一)

一.了解过滤器Filter 过滤器: Filter, 是 Servlet 技术中最实用的技术。过滤器是处于客户端和服务器之间的一个过滤网,可以过滤掉一些不符合要求的请求常见场景: Session 校验判断用户权限不符合设定条件,则会被重定向特殊的地址或者设定的响应过滤敏感词汇设置编…

一天撸一个财务APP系统【安卓端+前端+后端】

昨天有个粉丝朋友也想学开发Web和小程序、安卓,问可以在大学学会吗? 在学校学到的东西真的有限: 在很多的高校,有一些教授是学院派的,他们没有做过多少开发工作,上课就是照本宣科,讲的知识点都…

Vue打包优化篇-CDN加速

优化原因 在没有使用cdn加速之前打包后数据如下,可以看出element-ui、vue、vuex、vue-router这些依赖都打进chunk-vendors.js中导致体积很大,假设再来很多依赖项是不是更大,同时也会影响单页面应用首屏加载速度,所以这里采用一种打…

Vue的组件化编程

非单文件组件 注册局部组件 此时上面书写的组件都是局部组件,每一个vue实例要想使用上面的组件时都需要在components中进行注册才可以使用,此时如果再创建一个Vue实例vms,这个实例不在components中注册就直接使用组件会产生什么变化: 此时控制台报错 ‘是否正确注册了组件&a…

function 函数

一、函数的基本注意事项 function函数的名字也是一个标识符,通过关键字function申明一个函数 function 函数名(){ 代码块 } 二、函数基本用法 1、形参与实参 1、形参与实参可以有无数个,实参按照顺序赋值给形参; 2、实参个数不一定要与实…

web前端面试高频考点——Vue原理(理解MVVM模型、深度/监听data变化、监听数组变化、深入了解虚拟DOM)

系列文章目录 内容参考链接Vue基本使用Vue的基本使用(一文掌握Vue最基础的知识点)Vue通信和高级特性Vue组件间的通信及高级特性(多种组件间的通信、自定义v-model、nextTick、插槽)Vue高级特性Vue的高级特性(动态组件…

axios发post请求,后端接收不到参数的原因及解决

做分页数据时,使用vue3 axios发post请求,后端服务调用成功但数据没有根据参数动态变化,换为js ajax也是同样错误。 后来是后端没有接收到参数。 网上看了资料,原因: 使⽤axios请求数据时,我们的 …

Module Federation在vue3中使用vue2的组件

前言: 备注:本文基于对webpack Module Federation有一定了解的情况下 一般情况下使用模块联邦都是会使用相同的版本,如Vue2的组件时在Vue2中使用,但我为什么会在Vue3项目中去使用Vue2的组件呢,其实是因为历史原因。好…

点击《el-table》让选中的行变色,亲测实用

前期回顾 Vue项目实战 —— 哔哩哔哩移动端开发_0.活在风浪里的博客-CSDN博客撑着下班前半小时我用vue写《哔哩哔哩 项目》移动端、新手还在哭、老鸟一直在笑。。。技术选型Vue2,技术栈有axios、Vh等,下班过来敲哈哈https://blog.csdn.net/m0_5790…

vite+vue3+ts 手把手教你创建一个vue3项目

使用vite 创建一个vue3项目,基本全程cv。 安装router,less / scss,pinia,axios, element / Ant Design Vue,Echarts 以及如何配置别名,自定义组件,vue-devtools插件。 目录 1、创建…

vue设置cookie和路由守卫

vue项目中登录页面用户登录成功后,会把用户信息存储到cookie中,然后跳转进入首页,当用户没有登录时,直接输入页面地址会经过路由守卫检测cookie中是否存在用户信息,如果不存在,重定向到登录页让用户进行登录…

使用idea运行VUE项目

1.电脑先安装好node.js并配置好环境变量, 安装方法参考windows mac 2.使用管理员身份运行idea,把项目拉取下来, 并给idea安装vue的插件 安装方法参考链接 3.删除“node_modules”文件夹和“package-lock.json” 将项目里的“node_modules”…

简单的Java web项目代码(8个)

引言:Java web项目主要采用mvc的的设计思想,系统主要采用javajspservletmysqleclipse实现,具有登陆、分页、导出excel,增删改查等功能,适合初学者,满足基本的实训需求,以下是推荐的几款,总有适合…

uniapp及uniCloud开发中经常会出现的问题汇总

一、manifest.json内未配置Appld,请重新获取后再 uniCloud本地调试服务启动失败,错误信息为:manifest.json内未配置Appld,请重新获取后再试 新建uniapp项目会出现以下报错,说明还没有创建APPID。 解决办法: 打开DCloud开发者中心&#xff…

Vite基础配置之 - 分包

Vite基础配置之 - 分包 什么是分包呢?它有什么好处呢? 还是举个例子,来回忆一下吧,什么呢? 比如说,我使用了 loadsh.js 的东西,那么我们在打包的时候,就会把 loadsh 相关资源也会打…

AJAX跨域问题及解决方案

文章目录跨域哪些方式可以进行跨域部署服务器部署模块ajax1ajax2测试跨域解决方案方案1:设置响应头方案2:jsonp深入一下jsonp方案3:代理机制(httpclient)第一种方案:使用JDK内置的API第二种方案&#xff1a…

Vite 打包性能优化

Vite 打包性能优化开始一个 Vite ts 项目分包策略gzip 压缩cdn 加速开始一个 Vite ts 项目 这里我们开始了一个 Vite ts 的项目&#xff0c;其中关于 ts 的配置直接看内容注释即可 npm init -y npm i vite -D npm vite-plugin-checker -D #用来强制提示ts报错<!-- inde…