自己寫一個(gè)uniapp全局彈窗(APP端)
效果圖:

uniapp自帶的提示框不符合我們的要求,需要自己寫一個(gè)提示框,且全局通用。
解決思路:
使用 plus.nativeObj 來(lái)繪制窗口以及事件監(jiān)聽(tīng)。 官方文檔
方法如下:
1. 首先創(chuàng)建一個(gè)整個(gè)屏幕的控件,作為一個(gè)父容器。
此時(shí)還看不到任何東西
let screenHeight = uni.getSystemInfoSync().screenHeight;
let style = {
width:'100%',
height: (screenHeight + 'px'),
left:'0px',
top:'0px'
};
// 創(chuàng)建原生控件對(duì)象
// 參數(shù)1: id
// 參數(shù)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); 在控件上繪制,傳入繪制對(duì)象。
繪制對(duì)象文檔 可繪制圖片、矩形區(qū)域、文本等內(nèi)容。
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)`},
// 位置和大小. 下面的變量是根據(jù)屏幕寬高手動(dòng)計(jì)算的
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. 繪制標(biāo)題和內(nèi)容
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'}},
// 這個(gè)是內(nèi)容和底部按鈕的分割線
{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, // 文字內(nèi)容
textStyles:{size:'16px',color:'#fff'},
position:{top:titleTop+'px',left:startLeft+'px',width:width+'px',height:titleHeight+'px'}
},5. 創(chuàng)建確認(rèn)按鈕控件
我們需要給確認(rèn)按鈕設(shè)置點(diǎn)擊事件,所以它要作為一個(gè)新的控件,而不是再剛剛的控件上繼續(xù)繪制。
// 確認(rèn)
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'}},
]);設(shè)置點(diǎn)擊事件
viewconfirm.addEventListener("click",(e)=>{
// 發(fā)送事件
this.$event({res:true,types:'confirm'});
// 隱藏當(dāng)前控件(關(guān)閉)
this.hide();
},false);將 viewconfirm和view顯示出來(lái):
function show(){
this.view.show();
this.confirmModel.show();
}下面就是將這些掛載到Uni上就可以了。
下面是項(xiàng)目中的完整代碼:
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||"內(nèi)容"
let clickEvent=option.IsclickEvent||false;
let cancelVal=option.cancelVal||'取消';
let confirmVal=option.confirmVal||'確認(rèn)';
let cancelColor=option.cancelColor||'#fff'; // 取消
let confirmColor=option.confirmColor||'#fff'; // 確認(rèn)
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;
}
// 確認(rèn)
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);
//點(diǎn)擊蒙布
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動(dòng)畫結(jié)束');
// 關(guān)閉原生動(dòng)畫
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動(dòng)畫結(jié)束');
// 關(guān)閉原生動(dòng)畫
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_modelshow_modal.js: 用于創(chuàng)建promise對(duì)象并掛載
// 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
// 適應(yīng)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對(duì)象上
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:'未知錯(cuò)誤,請(qǐng)聯(lián)系管理員!',
delCancel: true,
confirmVal: '知道了', // 可選
cancelVal:'取消', // 可選
}).then(res=>{
// 點(diǎn)擊確認(rèn)按鈕點(diǎn)擊事件
}).catch(res=>{
// 點(diǎn)擊取消按鈕點(diǎn)擊事件
});總結(jié)
到此這篇關(guān)于uniapp全局彈窗(APP端)的文章就介紹到這了,更多相關(guān)uniapp全局彈窗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS實(shí)現(xiàn)六邊形3D拖拽翻轉(zhuǎn)效果的方法
這篇文章給大家分享一個(gè)利用javascript實(shí)現(xiàn)3D六邊形拖拽翻轉(zhuǎn)的效果實(shí)例,實(shí)現(xiàn)后的效果很贊,對(duì)大家的學(xué)習(xí)Javascript具有一定的參考借鑒價(jià)值,有需要的朋友們一起去來(lái)看看吧。2016-09-09
JavaScript實(shí)現(xiàn)twitter puddles算法實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)twitter puddles算法實(shí)例,本文源自twitter的一道面試題,本文使用js解開(kāi)了這首題,需要的朋友可以參考下2014-12-12
JavaScript中英文字符長(zhǎng)度統(tǒng)計(jì)方法示例【按照中文占2個(gè)字符】
這篇文章主要介紹了JavaScript中英文字符長(zhǎng)度統(tǒng)計(jì)方法,涉及javascript針對(duì)中英文字符的匹配與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-01-01
小程序選項(xiàng)卡以及swiper套用(跨頁(yè)面)
這篇文章主要為大家詳細(xì)介紹了小程序選項(xiàng)卡以及swiper套用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
詳談innerHTML innerText的使用和區(qū)別
下面小編就為大家?guī)?lái)一篇詳談innerHTML innerText的使用和區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08

