一、设计思路
1、创建一个弹窗页面组件
2、配置page.json,使页面跳转是在当前界面展示
3、定义uni全局全局属性
4、解决多个弹窗同时使用的冲突问题
注意:此方案不支持多个弹窗并存,有且仅有一个会展示,当前弹窗展示并关闭上一个弹窗
二、代码
1、index.vue---弹窗组件
<template>
<view>
<!-- 提示信息弹窗 2秒后消失-->
<!-- msgType:top、center、bottom、left、right、message、dialog、share -->
<view @click="itemClick('mask')" class="mask-content">
<uni-popup ref="message" type="message">
<uni-popup-message :type="info.msgType" :message="info.messageText"
:duration="info.duration"></uni-popup-message>
</uni-popup>
</view>
<!-- 加载弹窗 -->
<uni-popup ref="popupLoading" :is-mask-click="false">
<view class="popup-content"><text
class="cu-load load-cuIcon loading text-white">{{info.popupContent}}</text>
</view>
</uni-popup>
<!-- 提示信息弹窗 -->
<uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog :type="info.msgType" :cancelText="info.cancelText" :confirmText="info.confirmText"
:title="info.title" :content="info.content" @confirm="itemClick('confirm')" @close="itemClick('cancel')"
:duration="info.duration"></uni-popup-dialog>
</uni-popup>
<!-- 自定义提示框 -->
<view @click="itemClick('mask')" class="mask-content" v-if="info.isShow">
<view class="dialog-content" @click.stop="">
<view class="head-content " v-if="info.title" :style="info.content?'':'min-height:90rpx;padding:30rpx'">
<text>{{info.title}}</text>
</view>
<scroll-view class="main-content" scroll-y v-if="info.content">
<view class="info-content">
<text>{{info.content}}</text>
</view>
</scroll-view>
<view class="foot-content alert" v-if="'alert'==info.dialogType">
<view class="btn active" @click.stop="itemClick('confirm')">
{{info.confirmText}}
</view>
</view>
<view class="foot-content confirm" v-if="'confirm'==info.dialogType">
<view class="btn cancel" @click="itemClick('cancel')">
{{info.cancelText}}
</view>
<view class="btn active" @click.stop="itemClick('confirm')">
{{info.confirmText}}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'Dialog',
data() {
return {
info: {
//消息提示
msgType: 'success', //error、warn、info
messageText: '',
//确认框
content: "",
title: "提示",
duration: 2000,
cancelText: "取消",
confirmText: "确定",
dialogType: "", //弹窗类型 0:确认框 1:消息提示 2: 加载框
popupContent: "加载中....",
isShow: false,
isMaskClose: "1", //1点击遮罩层关闭弹窗
}
}
},
onLoad(info = {}) {
this.info = {
...this.info,
...info
};
this.getParams(this.info);
},
onUnload() {
this.popupLoadingClose();
this.info.dialogType = "";
},
methods: {
getParams(options) {
switch (options.dialogType) {
case "dialogOpen":
this.dialogOpen();
break;
case "messageOpen":
this.messageOpen();
break;
case "popupLoadingOpen":
this.popupContent = options.popupContent;
this.popupLoadingOpen();
break;
case "popupLoadingClose":
this.popupContent = options.popupContent;
this.popupLoadingClose();
break;
default:
break;
}
},
/**
* 确认框方法
*/
dialogOpen() {
this.$nextTick(() => {
this.$refs.alertDialog.open();
})
},
/**
* 消息提示框方法
*/
messageOpen() {
if (this.info.dialogType == "messageOpen") {
this.$nextTick(() => {
if(this.$refs.message){
this.$refs.message.open();
this.setTimeOut = setTimeout(() => {
uni.navigateBack()
}, this.info.duration)
}
});
}
},
/**
* 加载框方法
*/
popupLoadingOpen() {
this.$nextTick(() => {
this.$refs.popupLoading.open('center');
});
},
/**
* 废弃,页面路由使用不上
* 直接使用uni.navigateBack()
*/
popupLoadingClose() {
this.$refs.popupLoading.close();
},
itemClick(type) {
if (type == "mask" && this.info.isMaskClose != '1') {
return;
}
//解决消息提示的自动消失返回的bug
if (this.setTimeOut)
clearTimeout(this.setTimeOut);
uni.navigateBack();
uni.$emit("zy_common_dialog", type);
}
}
};
</script>
<style lang="scss">
$btncolor: #0081ff;
page {
background: transparent;
}
.mask-content {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
.dialog-content {
background-color: #FFFFFF;
width: 580rpx;
border-radius: 10rpx;
.head-content {
display: flex;
align-items: center;
justify-content: center;
color: #343434;
font-weight: bold;
font-size: 32rpx;
padding: 20rpx 30rpx;
}
.main-content {
max-height: 330rpx;
.info-content {
min-height: 80rpx;
padding: 10rpx 30rpx;
color: #636463;
font-size: 30rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
.foot-content {
display: flex;
justify-content: center;
align-items: center;
height: 110rpx;
.btn {
font-size: 28rpx;
border-radius: 66rpx;
height: 66rpx;
display: flex;
justify-content: center;
align-items: center;
}
&.alert {
.btn {
background-color: $btncolor;
color: #FFFFFF;
font-size: 28rpx;
border-radius: 60rpx;
height: 66rpx;
width: 300rpx;
padding: 0 40rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
&.confirm {
justify-content: space-around;
.btn {
min-width: 230rpx;
&.active {
background-color: $btncolor;
color: #FFFFFF;
}
&.cancel {
border: 1rpx solid $btncolor;
color: $btncolor;
border-radius: 66rpx;
}
}
}
}
}
}
</style>
2、工具类
2.1、dialog.js
export default {
/* 链接处理 */
getLink(params) {
let url = "/components/dialog/index";
if (params) {
let paramStr = "";
for (let name in params) {
paramStr += `&${name}=${params[name]}`
}
if (paramStr) {
url += `?${paramStr.substr(1)}`
}
}
return url;
},
// 将URL参数分割为对象键值对
getParam(curParam){
// 拼接参数
let param = ''
for (let key in curParam) {
param += '&' + key + '=' + curParam[key]
}
// 把参数保存为对像
let obj = {}
for (let key in curParam) {
obj[key] = curParam[key]
}
return obj
},
/* APP全局弹窗 */
dialog(params = {}, callback) {
this.back();
uni.navigateTo({
url: this.getLink(params),
success(e) {
if (callback != null && typeof callback == "function") {
uni.$off("zy_common_dialog");
uni.$on("zy_common_dialog", (type) => {
callback && callback(type)
})
}
}
})
},
/*弹出提示弹窗 */
alert(data = {}, callback, close) {
let params = {
dialogType: "alert",
isCloseBtn: '0',
isMaskClose: '0',
isShow:true,
...data
};
this.dialog(params, (type) => {
if ("confirm" == type) {
callback && callback()
} else {
close && close()
}
})
},
/*确认提示框弹窗 */
confirm(data = {}, confirm, cancel, close) {
let params = {
dialogType: "confirm",
isCloseBtn: '0',
isMaskClose: '0',
isShow:true,
...data
};
this.dialog(params, (type) => {
if ("confirm" == type) {
confirm && confirm()
} else if ("cancel" == type) {
cancel && cancel()
} else if ("close" == type) {
close && close()
}
})
},
/*确认提示框弹窗 */
dialogConfirm(data = {}, confirm, cancel, close) {
let params = {
dialogType: "dialogOpen",
...data
};
this.dialog(params, (type) => {
if ("confirm" == type) {
confirm && confirm()
} else if ("cancel" == type) {
cancel && cancel()
} else if ("close" == type) {
close && close()
}
})
},
/*消息提示框 */
showMessage(data = {}) {
let params = {
dialogType: "messageOpen",
isMaskClose: '1',
...data
};
this.dialog(params)
},
/**
* 加载框
*/
popupLoadingOpen(data = {}) {
let params = {
dialogType: "popupLoadingOpen",
...data
};
this.dialog(params)
},
back(isCheckPopupLoading=false){
//保证唯一弹窗
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
if(routes.length>1){
let curRoute = routes[routes.length - 1].route //获取当前页面路由
if(curRoute=="components/dialog/index"){
if(isCheckPopupLoading){
let curParam = routes[routes.length - 1].options; //获取路由参数
let paramObj=this.getParam(curParam);
if(paramObj.dialogType=="popupLoadingOpen")
uni.navigateBack();
}else{
uni.navigateBack();
}
}
}
}
}
2.2、dialogUtils.js
import dialog from "@/components/dialog/dialog.js"
module.exports = {
/**
* 弹出提示
*/
alert(content = "", title = "提示", callback, confirmText = '确定') {
// #ifdef APP-PLUS
dialog.alert({
content,
title,
confirmText
}, callback)
// #endif
// #ifndef APP-PLUS
uni.showModal({
title,
content,
confirmText,
showCancel: false,
confirmColor: "#e03c31",
success: callback
})
// #endif
},
/**
* 确认提示框
*/
confirm(content = "", confirm, cancel, confirmText = '确定', cancelText = '取消', title = "提示") {
// #ifdef APP-PLUS
dialog.confirm({
content,
title,
confirmText,
cancelText,
}, confirm, cancel)
// #endif
// #ifndef APP-PLUS
uni.showModal({
title,
content,
cancelText,
confirmText,
confirmColor: "#e03c31",
success: (e) => {
if (e.confirm) {
confirm && confirm()
} else if (e.cancel) {
cancel && cancel()
}
},
fail: (e) => {
console.log(e)
}
})
// #endif
},
/**
* 确认提示框
* @property {String} content 对话框内容
* @property {function} confirm 对话框内容
*/
dialogConfirm(content = "", confirm, cancel, confirmText = '确定', cancelText = '取消', msgType ='info', title = "提示") {
// #ifdef APP-PLUS
dialog.dialogConfirm({
content,
title,
confirmText,
cancelText,
msgType
}, confirm, cancel)
// #endif
// #ifndef APP-PLUS
uni.showModal({
title,
content,
cancelText,
confirmText,
confirmColor: "#e03c31",
success: (e) => {
if (e.confirm) {
confirm && confirm()
} else if (e.cancel) {
cancel && cancel()
}
},
fail: (e) => {
console.log(e)
}
})
// #endif
},
showMessage(messageText, msgType="success") {
// #ifdef APP-PLUS
dialog.showMessage({
msgType,
messageText
})
// #endif
// #ifndef APP-PLUS
uni.showToast({
title: content,
icon: 'none'
})
// #endif
},
popupLoadingOpen(popupContent = "加载中...") {
// #ifdef APP-PLUS
dialog.popupLoadingOpen({
popupContent
})
// #endif
// #ifndef APP-PLUS
uni.showToast({
title: content,
icon: 'none'
})
// #endif
},
popupLoadingClose() {
dialog.back(true);
}
}
三、使用方式
1、在uniapp的根目录下的components创建以下三个文件
2、配置page.json文件
{
"path": "components/dialog/index",
"style": {
"navigationStyle": "custom",
// #ifdef APP-PLUS
"backgroundColor": "transparent",
"backgroundColorTop": "transparent",
"backgroundColorBottom": "transparent",
// #endif
"app-plus": {
"animationType": "fade-in",
"background": "transparent",
"popGesture": "none"
}
}
}
3、在App.vue中定义全局变量,在原来的基础上添加以下代码
import dialog from '@/components/dialog/dialogUtils.js'
export default {
onLaunch: function() {
uni['dialog'] = dialog;
this.initApp()
}}
四、举例
1、提示弹窗
uni.dialog.alert("消息文本","提示",()=>{
uni.showToast({ title: '好的', icon:"none" });
},"好的");
2、确认弹窗
uni.dialog.confirm("这是一个确认弹窗",()=>{
uni.showToast({ title: '确定', icon:"none" });
},()=>{
uni.showToast({ title: '取消', icon:"none" });
});
3、uniapp自带的确认弹窗
uni.dialog.dialogConfirm("这是一个确认弹窗",()=>{
uni.showToast({ title: '确定', icon:"none" });
},()=>{
uni.showToast({ title: '取消', icon:"none" });
});
4、消息提示框---支持uniapp的组件的消息类型(success、info、error、warn)
uni.dialog.showMessage("1111");//默认sucess
uni.dialog.showMessage("1111","info");
uni.dialog.showMessage("1111","error");
uni.dialog.showMessage("1111","warn");
5、加载提示框
uni.dialog.popupLoadingOpen("正在努力加载中....");//打开加载框
uni.dialog.popupLoadingClose(); //关闭加载框
五、案例展示
1、
uni.dialog.confirm("是否提交?",()=>{
uni.dialog.popupLoadingOpen();
cancelForSAP(this.printing).then(res => {
//清空数据
this.clearData();
uni.dialog.alert(res.data,"sap凭证");//显示sap凭证
}).finally(fi => {
uni.dialog.popupLoadingClose();
})
});