自己写一个uniapp全局弹窗(APP端)

目录
  • 效果图:
  • 解决思路:
  • 方法如下:
    • 1. 首先创建一个整个屏幕的控件,作为一个父容器。
    • 2. 绘制遮罩层
    • 3.绘制通知框样式
    • 4. 绘制标题和内容
    • 5. 创建确认按钮控件
    • 下面是项目中的完整代码:
  • 总结

效果图:

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=>{
	// 点击取消按钮点击事件
});

总结

到此这篇关于uniapp全局弹窗(APP端)的文章就介绍到这了,更多相关uniapp全局弹窗内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 自己写一个uniapp全局弹窗(APP端)

    目录 效果图: 解决思路: 方法如下: 1. 首先创建一个整个屏幕的控件,作为一个父容器. 2. 绘制遮罩层 3.绘制通知框样式 4. 绘制标题和内容 5. 创建确认按钮控件 下面是项目中的完整代码: 总结 效果图: uniapp自带的提示框不符合我们的要求,需要自己写一个提示框,且全局通用. 解决思路: 使用 plus.nativeObj 来绘制窗口以及事件监听.    官方文档 方法如下: 1. 首先创建一个整个屏幕的控件,作为一个父容器. 此时还看不到任何东西 let screenHeig

  • 手把手教你写一个vue全局注册的Toast的实现

    目录 前言: 我们先思考下面的问题: 首先: 然后: 后来: 再且: 前言: 前几天客户经理不让我用某饿了么之类的UI库做一个轻提示之类的组件,当时一想我是饿了么战士,怎么会写哪个东西,然后我就想着用个alert糊弄过去,但是不行,然后我就细琢磨,发现Vue有个非常不错的Vue.extend. 经过一番努力,我学会了,可能是以前学的时候马虎漏掉了.不过问题不大,还能肝. 我们先思考下面的问题: 在写vue项目的时候啊,我们有了初始化的根实例之后,页面之间都是通过router进行管理,组件也是通过

  • 手把手教你写一个uniapp通用页面组件

    目录 前言 需求 开发 初始化页面数据 实现状态栏与底部配置 页面使用 总结 前言 做移动端项目时为了兼容各种手机型号的界面,最好有一个统一的页面组件对样式做统一处理,例如:判断是否显示状态栏,是否显示头部导航,是否空出底部区域等等,本篇会带大家从零到一开发一个 uniapp 的通用页面组件 需求 本次开发的页面,组件,需要完成以下功能 可配置控制是否显示原生导航,显示状态栏,并且也可以控制状态栏颜色 可配置控制是否留出底部固定区域 开发 初始化页面数据 编写页面组件类,获取系统配置,初始化样式

  • 封装一个vue中也可使用的uniapp的全局弹窗组件(任何页面都可以弹出)

    目录 效果图: 场景: 思路: 第一步: 第二步: 第三部:使用 总结 效果图: 场景: 当你对接websocket时,或者轮询也好,你需要获取到最新的信息,并且在任何页面弹出一个组件进行后续操作 思路: 1.先封装好要弹出的公共组件 2.向vue原型上挂载全局方法,拿到组件真实dom,从而对组件进行显隐操作 第一步: 创建一个公共组件,以下是组件全部的结构及样式,你需要把html中的两个image标签的路径换掉或者直接注释掉也行,html 和 css就不做解释了 invite.vue <tem

  • vue全局挂载实现APP全局弹窗的示例代码

    目录 需求背景 需求分析 代码展示 需求背景 app端对接网页端的客服系统,在用户实现网页客户系统发起询问时,app不论在哪个页面都需要弹窗提示 需求分析 这个需求分为两步,一个是负责双向实时通信,一个是全局显示.双向实时通信我们可以利用socket来实现,具体内容不展开(后续看情况再出一篇),本文主要讲全局显示. 代码展示 首先是写个弹窗组件,这里给出个demo.如下 <template> <view class="transferPopup-wrap" style

  • 写一个移动端惯性滑动&回弹Vue导航栏组件 ly-tab

    前段时间写了一个移动端的自适应滑动Vue导航栏组件,觉得有一定实用性,大家可能会用得到(当然有些大佬自己写得更好的话就没必要啦),于是前两天整理了一下,目前已经发布到npm和GitHub上了,点我到npm,点我到GitHub项目 ,有需要的同学可以在项目中 npm install ly-tab -S 或者 yarn add ly-tab 使用,具体用法下面会讲到. 好了,先看看效果吧 好的,开始废话了,实习差不多3个月了,这段时间跟着导师大佬也有接触过一些项目,也学到了不少东西,接触到的项目基本

  • 如何用原生js写一个弹窗消息提醒插件

    1.分析 当消息被触发的时候,会有一个自上而下的淡入过程. 在持续了一段时间后会自动的消失,或者是需要用户来手动的点击关闭按钮. 在消息消失的时候,会有一个自下而上的淡出过程. 消息是可以叠加弹出的,最新的消息会排在消息列表的最后面. 当前面的消息消失后,后面的消息会有一个向上滑动效果. 然后消息本身是有三部分组成 消息图标,用来区分不同类型的消息. 消息文本. 关闭按钮,并不是所有消息都需要关闭按钮. 2. 实现样式 那么,不管我们是用原生js还是vue,首先呢,我们都需要把这个消息的基本样式

  • 如何给ss bash 写一个 WEB 端查看流量的页面

    由于刚毕业的穷大学生,和朋友合租了一台服务器开了多个端口提供 ss 服务,懒得配置 ss-panel,就使用了 ss-bash 来监控不同端口的流量,但每次都要等上服务器才能看到流量使用情况,很麻烦,于是就写了个简单的页面来提供 WEB 访问. JavaScript 版本 用 crontab 定时把流量记录文件复制到 WEB 目录下,写个 JS 脚本作数据处理. function successFunction(data) { var allRows = data.split(/\r?\n|\r

  • uni-app中弹窗的使用与自定义弹窗

    目录 一.uni-app中自带的弹窗 二.实例 1.uni.showToast(OBJECT)(消息提示框) 2.uni.showModal(OBJECT)(显示两个按钮的提示框) 3.uni.showActionSheet(OBJECT)(从底部向上弹出操作菜单) 补充:uniapp自定义弹窗 总结 提示:以下是本篇文章正文内容,下面案例可供参考 一.uni-app中自带的弹窗 示例:在前端开发中,为了优化用户的交互体验,常需要用到弹窗来进行提示,引导用户操作,而js里的alter用起来是真的

  • 使用Vue写一个datepicker的示例

    前言 写插件是很有意思,也很锻炼人,因为这个过程中能发现许多的细节问题.在前端发展的过程中,jQuery无疑是一个重要的里程碑,围绕着这个优秀项目也出现了很多优秀的插件可以直接使用,大大节省了开发者们的时间.jQuery最重要的作用是跨浏览器,而现在浏览器市场虽不完美,但已远没有从前那么惨,数据驱动视图的思想倍受欢迎,大家开始使用前端框架取代jQuery,我个人比较喜欢Vue.js,所以想试着用Vue.js写一个组件出来. 为了发布到npm上,所以给项目地址改名字了,但是内部代码没有改,使用方法

随机推荐